hdu 6096 ac自动机 和 处理字符串分段输入
2017-09-30 19:54
381 查看
Bob has a dictionary with N words in it.
Now there is a list of words in which the middle part of the word has continuous letters disappeared. The middle part does not include the first and last character.
We only know the prefix and suffix of each word, and the number of characters missing is uncertain, it could be 0. But the prefix and suffix of each word can not overlap.
For each word in the list, Bob wants to determine which word is in the dictionary by prefix and suffix.
There are probably many answers. You just have to figure out how many words may be the answer.
InputThe first line of the input gives the number of test cases T; T test cases follow.
Each test case contains two integer N and Q, The number of words in the dictionary, and the number of words in the list.
Next N line, each line has a string Wi, represents the ith word in the dictionary (0<|Wi|≤1000000<|Wi|≤100000)
Next Q line, each line has two string Pi , Si, represents the prefix and suffix of the ith word in the list (0<|Pi|,|Si|≤100000,0<|Pi|+|Si|≤1000000<|Pi|,|Si|≤100000,0<|Pi|+|Si|≤100000)
All of the above characters are lowercase letters.
The dictionary does not contain the same words.
Limits
T≤5T≤5
0<N,Q≤1000000<N,Q≤100000
∑Si+Pi≤500000∑Si+Pi≤500000
∑Wi≤500000∑Wi≤500000
OutputFor each test case, output Q lines, an integer per line, represents the answer to each word in the list.
Sample Input
Sample Output
ac自动机 最新板子解法
#include <bits/stdc++.h>
using namespace std;
#define maxm 505000*3
const int M = 505000*3;
char str[maxm];
int ans[M];
const int SIGMA_SIZE=27;
struct AC
{
int ch[maxm][27];
int val[maxm];
int height[maxm];
int fail[maxm],last[maxm];
int sz;
void clear(){memset(ch[0],0,sizeof(ch[0]));sz=1;}
int idx(char x){return x-'a';}
int insert(char *s)
{
int u=0;
int n=strlen(s);
for(int i=0;i<n;i++)
{
int c=idx(s[i]);
if(!ch[u][c])
{
memset(ch[sz],0,sizeof(ch[sz]));
height[sz]=height[u]+1;
val[sz]=0;
ch[u][c]=sz++;
}
u=ch[u][c];
}
val[u]++;
return u;
}
void getfail()
{
queue<int> q;
fail[0]=0;
int u=0;
for(int i=0;i<SIGMA_SIZE;i++)
{
u=ch[0][i];
if(u){q.push(u);fail[u]=0;last[u]=0;}
}
while(!q.empty())
{
int r=q.front();q.pop();
for(int i=0;i<SIGMA_SIZE;i++)
{
u=ch[r][i];
if(!u){ch[r][i]=ch[fail[r]][i];continue;}
q.push(u);
int v=fail[r];
while(v&&!ch[v][i])v=fail[v];
fail[u]=ch[v][i];
last[u]=val[fail[u]]?fail[u]:last[fail[u]];
}
}
}
int find(char *s,int le)
{
int u=0,cnt=0;
for(int i=0;s[i];i++)
{
int c=idx(s[i]);
u=ch[u][c];
int temp=0;//必须赋初值为0,表示如果下面两个判断都不成立的时候while可以正常执行
if(val[u])
temp=u;
else if(last[u])
temp=last[u];
while(temp)
{
if(height[temp]<=le)
ans[temp]++;
temp=last[temp];
}
}
}
}tree;
int d[M],st[M];
const int N = 100100;
int len
;
char *s
;
int pos
;
char ss[M],t1[M],t2[M];
int main()
{
int T,n,i;
scanf("%d",&T);
while(T--){
int n,m;
tree.clear();
memset(ans,0,sizeof(ans));
scanf("%d%d",&n,&m);
int del=0;
int j=0;
for(int i=1;i<=n;i++)
{
s[i]=ss+j;
scanf(" %s",s[i]);
len[i]=strlen(s[i])+1;
j+=len[i];
strcpy(ss+j,s[i]);
ss[j-1]='z'+1;
j+=len[i];
}
for(int i=1;i<=m;i++)
{
scanf(" %s %s",t1+1,t2);
t1[0]='z'+1;
strcat(t2,t1);
pos[i]=tree.insert(t2);
}
tree.getfail();
for(int i=1;i<=n;i++)
{
tree.find(s[i],len[i]);
}
for(int i=1;i<=m;i++) printf("%d\n",ans[pos[i]] );
}
return 0;
}
Now there is a list of words in which the middle part of the word has continuous letters disappeared. The middle part does not include the first and last character.
We only know the prefix and suffix of each word, and the number of characters missing is uncertain, it could be 0. But the prefix and suffix of each word can not overlap.
For each word in the list, Bob wants to determine which word is in the dictionary by prefix and suffix.
There are probably many answers. You just have to figure out how many words may be the answer.
InputThe first line of the input gives the number of test cases T; T test cases follow.
Each test case contains two integer N and Q, The number of words in the dictionary, and the number of words in the list.
Next N line, each line has a string Wi, represents the ith word in the dictionary (0<|Wi|≤1000000<|Wi|≤100000)
Next Q line, each line has two string Pi , Si, represents the prefix and suffix of the ith word in the list (0<|Pi|,|Si|≤100000,0<|Pi|+|Si|≤1000000<|Pi|,|Si|≤100000,0<|Pi|+|Si|≤100000)
All of the above characters are lowercase letters.
The dictionary does not contain the same words.
Limits
T≤5T≤5
0<N,Q≤1000000<N,Q≤100000
∑Si+Pi≤500000∑Si+Pi≤500000
∑Wi≤500000∑Wi≤500000
OutputFor each test case, output Q lines, an integer per line, represents the answer to each word in the list.
Sample Input
1 4 4 aba cde acdefa cdef a a cd ef ac a ce f
Sample Output
2 1 10
ac自动机 最新板子解法
#include <bits/stdc++.h>
using namespace std;
#define maxm 505000*3
const int M = 505000*3;
char str[maxm];
int ans[M];
const int SIGMA_SIZE=27;
struct AC
{
int ch[maxm][27];
int val[maxm];
int height[maxm];
int fail[maxm],last[maxm];
int sz;
void clear(){memset(ch[0],0,sizeof(ch[0]));sz=1;}
int idx(char x){return x-'a';}
int insert(char *s)
{
int u=0;
int n=strlen(s);
for(int i=0;i<n;i++)
{
int c=idx(s[i]);
if(!ch[u][c])
{
memset(ch[sz],0,sizeof(ch[sz]));
height[sz]=height[u]+1;
val[sz]=0;
ch[u][c]=sz++;
}
u=ch[u][c];
}
val[u]++;
return u;
}
void getfail()
{
queue<int> q;
fail[0]=0;
int u=0;
for(int i=0;i<SIGMA_SIZE;i++)
{
u=ch[0][i];
if(u){q.push(u);fail[u]=0;last[u]=0;}
}
while(!q.empty())
{
int r=q.front();q.pop();
for(int i=0;i<SIGMA_SIZE;i++)
{
u=ch[r][i];
if(!u){ch[r][i]=ch[fail[r]][i];continue;}
q.push(u);
int v=fail[r];
while(v&&!ch[v][i])v=fail[v];
fail[u]=ch[v][i];
last[u]=val[fail[u]]?fail[u]:last[fail[u]];
}
}
}
int find(char *s,int le)
{
int u=0,cnt=0;
for(int i=0;s[i];i++)
{
int c=idx(s[i]);
u=ch[u][c];
int temp=0;//必须赋初值为0,表示如果下面两个判断都不成立的时候while可以正常执行
if(val[u])
temp=u;
else if(last[u])
temp=last[u];
while(temp)
{
if(height[temp]<=le)
ans[temp]++;
temp=last[temp];
}
}
}
}tree;
int d[M],st[M];
const int N = 100100;
int len
;
char *s
;
int pos
;
char ss[M],t1[M],t2[M];
int main()
{
int T,n,i;
scanf("%d",&T);
while(T--){
int n,m;
tree.clear();
memset(ans,0,sizeof(ans));
scanf("%d%d",&n,&m);
int del=0;
int j=0;
for(int i=1;i<=n;i++)
{
s[i]=ss+j;
scanf(" %s",s[i]);
len[i]=strlen(s[i])+1;
j+=len[i];
strcpy(ss+j,s[i]);
ss[j-1]='z'+1;
j+=len[i];
}
for(int i=1;i<=m;i++)
{
scanf(" %s %s",t1+1,t2);
t1[0]='z'+1;
strcat(t2,t1);
pos[i]=tree.insert(t2);
}
tree.getfail();
for(int i=1;i<=n;i++)
{
tree.find(s[i],len[i]);
}
for(int i=1;i<=m;i++) printf("%d\n",ans[pos[i]] );
}
return 0;
}
相关文章推荐
- HDU-1274-展开字符串(dfs分段字符串处理)
- hdu 1013 Digital Roots(字符输入,字符串处理)
- hdu 1048 The Hardest Problem Ever (string特点运用!!!字符串输入处理)
- POJ 3094 字符串处理及空格输入
- HDU 1073 Online Judge(字符串输入方面的经验)
- HDU-1039-Easier Done Than Said?(简单字符串处理)
- 如何用java实现不同编码方式字符串的转换(包含异常处理、重复不终止输入、缓冲区bufferedreader的使用)
- 10-过滤输入字符串中的危险字符(字符串处理)
- 语法分析器--输入字符串处理
- HDU 2089 数位dp/字符串处理 两种方法
- 【HDU 3183】 字符串处理
- HDU 6096:妙用AC自动机(666)
- hdu 1048 字符串处理
- hdu 1106(字符串处理+排序)
- hdu 2265 Encoding The Diary (基础的字符串处理,巨简单)
- HDU 3746 Cyclic Nacklace kmp处理字符串周期问题
- C++错误输入的处理--整型错误输入字符串
- HDU 5414(2015多校10)-CRB and String(字符串处理)
- hdu 2532 Engine 模拟好题 字符串的处理
- hdu3783 ZOJ字符串处理