题意:查询 一个串中所有不同构的循环子串在 主串中出现的次数。
思路: 我们用增量的方式进行考虑,维护当前匹配到的转态,当前串的长度。当加入一个字符时,我们考虑如何维护转移就做出来了。
第一次 1A 2700分的题,有点小激动。
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1000005;
int righ[maxn<<1],vis[maxn<<1];
const int ch_size = 26;
struct SAM{
int fa[maxn*2], // 后缀链接
ch[maxn*2][ch_size],
len[maxn*2], //该节点最长串的长度
tot, // 节点总数
last; // 代表当前的整个串
void init(){
tot = last = 0;
fa[0] = -1;
len[0] = 0;
memset( ch[0],0,sizeof( ch[0] ) );
}
void extend( int x ){
int p = last;
int cur = ++tot;
memset( ch[cur],0,sizeof( ch[cur] ) );
len[cur] = len[last]+1;
while( p != -1 && !ch[p][x] ){
ch[p][x] = cur;
p = fa[p];
}
if( p == -1 ){
fa[cur] = 0;
}else {
int q = ch[p][x];
if (len[q] == len[p] + 1) {
fa[cur] = q;
} else {
int clone = ++tot;
len[clone] = len[p] + 1;
for (int i = 0; i < ch_size; i++) {
ch[clone][i] = ch[q][i];
}
fa[clone] = fa[q];
fa[q] = fa[cur] = clone;
while (p != -1) {
if (ch[p][x] == q)ch[p][x] = clone;
else break;
p = fa[p];
}
}
}
last = cur;
}
}g;
char str[maxn];
int c[maxn],b[maxn<<1];
void radix( int len ){
memset( c,0,sizeof(c) );
for( int i = 1;i <= g.tot;i++ ) c[ g.len[i] ]++;
for( int i = 2;i <= len;i++ ) c[i] += c[i-1];
for( int i = 1;i <= g.tot;i++ ) b[c[ g.len[i] ]--] = i;
}
int tim;
int solve(){
int len = strlen(str),p = 0,cnt = 0,res = 0,sum = 0,j = 0;
while( cnt < 2 ){
if( j == len-1 ) cnt++;
if( cnt >= 2 ) break;
int c = str[j]-'a';
if( g.ch[p][c] ){
p = g.ch[p][c];sum ++;
if( sum == len ){
if( vis[p] != tim )
res += righ[p];
vis[p] = tim;
sum--;
if( g.len[ g.fa[p] ] >= sum ) {
p = g.fa[p];
}
}
}else{
while( p != -1 && !g.ch[p][c] ){
p = g.fa[p];sum = g.len[p];
}
if( p == -1 ) break;
p = g.ch[p][c];
sum++;
}
j = (j+1)%len;
}
return res;
}
int main(){
scanf("%s",str);
int len =strlen(str);
g.init();
for( int i = 0; i < len;i++ ){
g.extend( str[i]-'a' );
righ[ g.last ] = 1;
}
radix( len );
for( int i = g.tot;i >= 1;i-- ){
int j = b[i];
righ[ g.fa[j] ] += righ[j];
}
int n;scanf("%d",&n);
for( int i = 1;i <= n;i++ ){
tim++;
scanf("%s",str);
int ans =solve();
printf("%d\n",ans);
}
return 0;
}