动态在尾部加入字符,统计相同字符串出现次数 >= k 得字符串有多少个。
0 0很显然用 SAM来做。 每次当这个节点出现了k次之后,就增加了 p->cnt - p->f-cnt 得数目得子串
用cout竟然超时了。0 0.。。 哎。。换成printf才过掉。。坑于cout
#include <cstdio>
#include <cstdlib>
#include <iostream>
using namespace std;
const int MAX_NODES = 1006666;
const int N = 755555;
struct node{
struct node* ch[26];
struct node* f;
int mx,cnt;
void init(){
memset(ch,0,sizeof(ch));
f = 0; mx = 0 ; cnt = 0;
}
int calc(){
return mx-f->mx;
}
}*root,*cur,*tail,pool[MAX_NODES];
bool vis[MAX_NODES];
void add(int c){
node *p = tail, *np = cur++;np->init();
for( ; p && !p->ch[c] ;p=p->f) p->ch[c] = np;
np->mx = tail->mx+1;
tail = np ;
if(!p) np->f = root;
else
if(p->mx+1 == p->ch[c]->mx) np->f = p->ch[c];
else{
node * q = p->ch[c] , *r = cur++;
*r = *q;
r->mx = p->mx+1;
q->f = np->f = r;
for(; p && p->ch[c] == q ; p=p->f) p->ch[c] = r;
}
}
char s[N];
int len;
long long ans;
int n,m,k;
void cc(){
node *p = tail;
for( ; p != root && !vis[p-root]; p = p->f){
if(p->cnt>=k) break; // 判断父亲节点是否已经计算过了。。
p->cnt++;
if(p->cnt>=k){
ans += p->calc();
}
}
}
void suffix_auto_init(){
int i;
ans = 0;
root = cur = tail = pool; cur++; root->init();
for(i = 0; s[i] ;i++){
add(s[i]-'a');
cc();
}
len = i;
}
char ts[10];
int main(){
int q,vq;
while(scanf("%d %d %d",&n,&m,&k)!=EOF){
scanf("%s",s);
suffix_auto_init();
while(m--){
scanf("%d",&vq);
if(vq==2){
printf("%I64d\n",ans);
}else{
scanf("%s",ts);
add(ts[0]-'a');
cc();
}
}
}
return 0;
}