题目连接:http://blog.csdn.net/SolarDomo/article/category/6354437
题意:问模式串在主串和主串的逆串中出现多少个
建自动机之后,把正串和反串都跑一边自动机,遍历到的VALUE值的清空
代码:
#include <bits/stdc++.h>
#define sf scanf
#define pf printf
using namespace std;
const int maxn = 250000 + 5,sigma_size = 26;
int ch[maxn][sigma_size],value[maxn],tot,fail[maxn];
void Init_Trie(){
memset(ch[0],0,sizeof ch[0]);
value[0] = 0;tot = 1;
}
void Insert(char *s,int v){
int cur = 0,idx;
while(*s){
idx = *s - 'A';
if(!ch[cur][idx]){
memset(ch[tot],0,sizeof ch[tot]);
value[tot] = 0;
ch[cur][idx] = tot++;
}cur = ch[cur][idx];
s++;
}
value[cur]++;
}
void GetFail(){
queue<int> Q;
Q.push(0);fail[0] = -1;
while(!Q.empty()){
int cur = Q.front();Q.pop();
for(int i = 0;i <sigma_size;++i){
if(ch[cur][i]){
int f = fail[cur];
while(f != -1 && ch[f][i] == 0) f = fail[f];
fail[ch[cur][i]] = (f == - 1) ? 0 : ch[f][i];
Q.push(ch[cur][i]);
}
else{
ch[cur][i] = (cur == 0) ? 0 : ch[fail[cur]][i];
}
}
}
}
int Search(char *s){
int cur = 0,ret = 0;
while(*s){
int idx = *s - 'A';
cur = ch[cur][idx];
if(value[cur]){
int tmp = cur;
while(tmp){
ret += value[tmp];value[tmp] = 0;
tmp = fail[tmp];
}
}
s++;
}
return ret;
}
const int maxc = 5100000 + 5;
char str[maxc],tmpc;
int main(){
int T;sf("%d",&T);
while(T--){
Init_Trie();
int n;sf("%d",&n);
while(n--){
sf("%s",str);
Insert(str,1);
}tmpc = getchar();
int len = 0;
while(tmpc = getchar()){
if(tmpc == '\n') break;
else if(tmpc == '['){
int cnt;sf("%d",&cnt);tmpc = getchar();
while(cnt--){
str[len++] = tmpc;
}
getchar();
}
else{
str[len++] = tmpc;
}
}str[len] = '\0';
GetFail();
int ret = Search(str);
strrev(str);ret += Search(str);
pf("%d\n",ret);
}
}