标签:static http mem zoj push reg memset clear front
先把模板串都丢进AC自动机
然后跑查询
对于允许重叠的,我们直接对\(fail\)树上一段路径的节点的答案++
否则我们分串的长度讨论,对于每种长度的串处理一个答案\(dp[i][6]\)
int n;
char s[N][10],str[N];
int kind[N],End[N];
const int SIZE=N*6;
int dp[SIZE][7],pre[SIZE][7];
namespace AC{
int trie[SIZE][26];
int fail[SIZE],cnt;
void clear(){
cnt=0;
memset(trie,0,sizeof trie);
}
int Insert(char *s){
int p=0;
rep(i,0,strlen(s)-1) {
int x=s[i]-‘a‘;
((!trie[p][x])&&(trie[p][x]=++cnt));
p=trie[p][x];
}
return p;
}
void Build(){
static queue <int> que;
rep(i,0,25) if(trie[0][i]) {
que.push(trie[0][i]);
fail[trie[0][i]]=0;
}
while(!que.empty()) {
int u=que.front(); que.pop();
rep(i,0,25) {
int &v=trie[u][i];
if(v) {
fail[v]=trie[fail[u]][i];
que.push(v);
} else v=trie[fail[u]][i];
}
}
}
void Que(char *s) {
memset(dp,0,sizeof dp);
memset(pre,-63,sizeof pre);
int p=0;
rep(i,0,strlen(s)-1) {
p=trie[p][s[i]-‘a‘];
for(reg int j=p; j; j=fail[j]) {
dp[j][0]++;
rep(k,1,6) {
if(i-pre[j][k]>=k) {
dp[j][k]++;
pre[j][k]=i;
}
}
}
}
}
}
int main(){
int kase=0;
while(~scanf("%s",str)) {
printf("Case %d\n",++kase);
AC::clear();
n=rd();
rep(i,1,n) {
kind[i]=rd();
scanf("%s",s[i]);
if(kind[i]) kind[i]=strlen(s[i]);
End[i]=AC::Insert(s[i]);
}
AC::Build();
AC::Que(str);
rep(i,1,n) printf("%d\n",dp[End[i]][kind[i]]);
puts("");
}
}
标签:static http mem zoj push reg memset clear front
原文地址:https://www.cnblogs.com/chasedeath/p/12931249.html