询问

Time Limit:2000MS Memory Limit:65536KB
Total Submit:286 Accepted:70

Description 

Pollux最近对字符串匹配很感兴趣,他渐渐发现一个有趣的函数,并且他觉得利用这个函数或许可以建立一种新的匹配算法:
对于字符串S[1…n]和i∈[1 , n] ,定义F(i) 为S 和 S[1…i] 的最长公共后缀的长度.
例如对于串S[1…11] = zaaxbaacbaa ,则F(1) = 0 ,F(2) = 1 , F(3) = 2( 注意S[1…3] = zaa ) ,F(4) = 0 , …… F(10) = 1 ,F(11) = 11 ;
对于串S[1…n],i∈[1 , n] ,S[i…n] 为S的后缀;
但是有一点让他犯难的地方就是他不知道如何快速的计算这个函数在i∈[1 , n]的值,作为ECNU的一名编程高手,你能帮助他解决这个问题吗?

Input 

第一行为一个整数T,表示测数数据的组数.
对于每组数据:
第一行为一个字符串S,只由小写字母组成,如果len(s)表示s的长度,那么1 <= len(s) <= 1000000 ;
接下来一个数N( 1 <= N <= 100000 ),表示询问的次数;
接下来N行,每行一个数x( 1<=x<=len(s))。

Output 

对于每个x输出F(x);

Sample Input 

1
zaaxbaacbaa
11
1
2
3
4
5
6
7
8
9
10
11

Sample Output 

0
1
2
0
0
1
3
0
0
1
11

Source

解题:没想到别的什么办法,只好用后缀数组了

 #include <bits/stdc++.h>
using namespace std;
const int maxn = ;
char s[maxn];
int sa[maxn],t[maxn],t2[maxn];
int height[maxn],rk[maxn],c[maxn],n;
void build_sa(int m) {
int i,*x = t,*y = t2;
for(i = ; i < m; ++i) c[i] = ;
for(i = ; i < n; ++i) c[x[i] = s[i]]++;
for(i = ; i < m; ++i) c[i] += c[i-];
for(i = n-; i >= ; --i) sa[--c[x[i]]] = i; for(int k = ; k <= n; k <<= ) {
int p = ;
for(i = n-k; i < n; ++i) y[p++] = i;
for(i = ; i < n; ++i)
if(sa[i] >= k) y[p++] = sa[i] - k;
for(i = ; i < m; ++i) c[i] = ;
for(i = ; i < n; ++i) c[x[y[i]]]++;
for(i = ; i < m; ++i) c[i] += c[i-];
for(i = n-; i >= ; --i) sa[--c[x[y[i]]]] = y[i];
swap(x,y);
x[sa[]] = ;
for(p = i = ; i < n; ++i)
x[sa[i]] = y[sa[i]] == y[sa[i-]] && y[sa[i]+k] == y[sa[i-]+k]?p-:p++;
if(p >= n) break;
m = p;
}
}
void getHeight() {
int i,j,k = ;
for(i = ; i < n; ++i) rk[sa[i]] = i;
for(i = ; i < n; ++i) {
if(k) --k;
j = sa[rk[i]-];
while(i + k < n && j + k < n && s[i+k] == s[j+k]) ++k;
height[rk[i]] = k;
}
}
int st[maxn][],m;
void initRMQ() {
memset(st,,sizeof st);
for(int i = ; i < n; ++i) st[i][] = height[i];
for(int i = ; (<<i) < n; ++i)
for(int j = ; j + (<<i) <= n; ++j)
st[j][i] = min(st[j][i-],st[j+(<<(i-))][i-]);
}
int query(int s,int t) {
if(s == t) return n - - s;
s = rk[s];
t = rk[t];
if(s > t) swap(s,t);
s++;
int k = log2(t - s + );
return min(st[s][k],st[t-(<<k)+][k]);
}
int main() {
int kase;
scanf("%d",&kase);
while(kase--) {
scanf("%s",s);
n = strlen(s)+;
reverse(s,s+n-);
build_sa();
getHeight();
initRMQ();
scanf("%d",&m);
while(m--) {
int tmp;
scanf("%d",&tmp);
printf("%d\n",query(,n - - tmp));
}
}
return ;
}

最新文章

  1. NRF51822之ADC(1)
  2. [No000029]程序员的那些事儿 -- 皆大欢喜的加薪
  3. yii2.0 输出url 注册js css文件
  4. SpringMVC + Spring + MyBatis 学习笔记:为MyBatis增加打印SQL功能 (最简化配置)
  5. Tkinter教程之Entry篇
  6. File-nodejs
  7. React-nwb的使用
  8. poj2409 Let it Bead
  9. JSP 语法/标签
  10. asp.net路径问题
  11. 北京大学Cousera学习笔记--5-计算导论与C语言基础--计算机的基本原理-设计程序
  12. SHELL脚本--简介
  13. Django中model层详解
  14. css中px,em,rem,rpx的区别
  15. Python数字与字符之间的转换
  16. xcode 定义自己的代码片段
  17. U3D GPU蒙皮
  18. delphichromiumembedded
  19. 制作rpm安装包
  20. 笔记-python-float(‘inf’)

热门文章

  1. UWP连接mysql 实现数据远程备份
  2. 数据库应用_innobackupex备份与恢复
  3. 如何取未知Json字符串 某个主键取对应的Value
  4. the prblem 3n+1
  5. Debian9.5系统DHCP服务器ISC DHCP软件配置说明
  6. Python2x,3x源码的区别,编译型解释型,变量,注释,if,用户交互input,基本数据类型3种
  7. php nusoap类的使用、用法、出错 及说明
  8. JavaScript函数练习
  9. Axios 使用时遇到的问题
  10. Solr教程--官方自带数据的三个练习及讨论翻译版本