hdu_5507_GT and strings(AC自动机)

题目链接:hdu_5507_GT and strings

题意:给n个字符串和q个询问,每个询问给两个数字x,y,问1.x是否为y的子序列,2.x是否为y的子串,是输出1,否则输出0,每个询问输出2个数字

题解:

对于子序列,朴素的做法,每次询问的复杂度为max(str[x],str[y]),题目好像有数据卡这个做法,反正会T,正解应该是建立一个序列自动机,首先将所有的字符串连续存起来,用数组来保存每个字符串的位置,然后dp[i][j]表示第i个字符的下一个字符的位置,询问的时候就能做到复杂度为min(str[x],str[y])。、

对于子串,可以用AC自动机来预处理,子串的询问有点特别,不是一般的在树上走,而是对每个节点进行寻找,然后用map来记录关系,不过在询问的时候也有个优化,不加这个优化一样会T,加了瞬间变成170+ms,具体看代码。

 1 #include<bits/stdc++.h>
 2 #define F(i,a,b) for(int i=a;i<=b;i++)
 3 using namespace std;
 4 typedef pair<int,int>P;
 5
 6 const int N=1e5+7;
 7 int t,n,m,L[N],R[N],loc[N],dp[N][26],Q[N][2],ans[N][2];
 8 char str[N];
 9 map<P,int>ok;
10 const int AC_N=N,tyn=26;//数量乘串长,类型数
11 struct AC_automation{
12     int tr[AC_N][tyn],cnt[AC_N],Q[AC_N],fail[AC_N],tot;
13     inline int getid(char x){return x-‘a‘;}
14     void nw(){cnt[++tot]=0,fail[tot]=0;memset(tr[tot],0,sizeof(tr[tot]));}
15     void init(){tot=-1,fail[0]=-1,nw();}
16     void insert(int l,int r,int x=0){
17         for(int i=l,w;i<=r;x=tr[x][w],loc[i]=x,i++)
18             if(!tr[x][w=getid(str[i])])nw(),tr[x][w]=tot;
19         cnt[x]++;//串尾标记
20     }
21     void build(int head=1,int tail=0){
22         for(int i=0;i<tyn;i++)if(tr[0][i])Q[++tail]=tr[0][i];
23         while(head<=tail)for(int x=Q[head++],i=0;i<tyn;i++)
24             if(tr[x][i])fail[tr[x][i]]=tr[fail[x]][i],Q[++tail]=tr[x][i];
25             else tr[x][i]=tr[fail[x]][i];
26     }
27     void ask(int l,int r)
28     {
29         F(i,l,r)for(int p=loc[i];p;p=fail[p])
30             if(cnt[p])ok[P(p,loc[r])]=1;
31             else if(fail[p]&&!cnt[fail[p]])fail[p]=fail[fail[p]];//决定是否T的优化
32     }
33 }AC;
34
35 void work1()
36 {
37     F(i,0,25)dp[R[n]+1][i]=N;//建立“子序列自动机”
38     for(int i=R[n];i>=1;i--)F(j,0,25)
39         if(str[i]==j+‘a‘)dp[i][j]=i;
40             else dp[i][j]=dp[i+1][j];
41     F(i,1,m)
42     {
43         int x=Q[i][0],y=Q[i][1];
44         if(R[x]-L[x]>R[y]-L[y])ans[i][0]=0;
45         else
46         {
47             ans[i][0]=1;
48             for(int j=L[x],p=L[y];j<=R[x];j++,p++)
49             {
50                 p=dp[p][str[j]-‘a‘];
51                 if(p>R[y]){ans[i][0]=0;break;}
52             }
53         }
54     }
55 }
56
57 void work2()
58 {
59     AC.init(),ok.clear();
60     F(i,1,n)AC.insert(L[i],R[i]);
61     AC.build();
62     F(i,1,n)AC.ask(L[i],R[i]);
63     F(i,1,m)ans[i][1]=ok[P(loc[R[Q[i][0]]],loc[R[Q[i][1]]])];
64 }
65
66 int main()
67 {
68     scanf("%d",&t);
69     while(t--)
70     {
71         scanf("%d%d",&n,&m);
72         int ed=1;
73         F(i,1,n)
74         {
75             scanf("%s",str+ed);
76             int len=strlen(str+ed);
77             L[i]=ed,R[i]=ed+len-1,ed=R[i]+1;
78         }
79         F(i,1,m)scanf("%d%d",&Q[i][0],&Q[i][1]);
80         work1(),work2();
81         F(i,1,m)printf("%d%d",ans[i][0],ans[i][1]);
82         puts("");
83     }
84     return 0;
85 }

时间: 2024-10-11 22:21:03

hdu_5507_GT and strings(AC自动机)的相关文章

UVALive - 4811 Growing Strings (AC自动机+dp)

题目链接:UVALive - 4811 Growing Strings 题意: 给你n个字符串,问你最多能选出多少个字符串,使得s[i]是s[i+1]的子串. 题解: 先将所有的字符串插入AC自动机,将所有字符串按长度排序后,显然dp[i]=max{dp[j]}+1,其中s[j]是s[i]的子串.然后就完了. 1 #include<bits/stdc++.h> 2 #define mst(a,b) memset(a,b,sizeof(a)) 3 #define F(i,a,b) for(int

UVA 10679 I love Strings!!!(AC自动机)

http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=1620 题意: 给出一个文本串和若干个模式串,问模式串是否在文本串中出现过. 分析: 简单粗暴的AC自动机模板题,要注意模式串可能有重复的情况. /* * * Author : fcbruce * * Time : Sat 04 Oct 2014 03:30:15 PM CST * */ #i

hdu5384 AC自动机模板题,统计模式串在给定串中出现的个数

http://acm.hdu.edu.cn/showproblem.php?pid=5384 Problem Description Danganronpa is a video game franchise created and developed by Spike Chunsoft, the series' name is compounded from the Japanese words for "bullet" (dangan) and "refutation&q

poj 3691 DNA repair(AC自动机+dp)

DNA repair Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 5877   Accepted: 2760 Description Biologists finally invent techniques of repairing DNA that contains segments causing kinds of inherited diseases. For the sake of simplicity, a

HDU-3247 Resource Archiver(AC自动机+BFS)

Description Great! Your new software is almost finished! The only thing left to do is archiving all your n resource files into a big one. Wait a minute- you realized that it isn't as easy as you thought. Think about the virus killers. They'll find yo

hdu 2457 AC自动机+dp

DNA repair Time Limit: 5000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 2004    Accepted Submission(s): 1085 Problem Description Biologists finally invent techniques of repairing DNA that contains segments c

HDU 5384——Danganronpa——————【AC自动机】

Danganronpa Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)Total Submission(s): 582    Accepted Submission(s): 323 Problem Description Danganronpa is a video game franchise created and developed by Spike Chunsoft

hdu 1686 ac自动机

Problem Description The French author Georges Perec (1936–1982) once wrote a book, La disparition, without the letter 'e'. He was a member of the Oulipo group. A quote from the book:Tout avait Pair normal, mais tout s’affirmait faux. Tout avait Fair

AC自动机- 自我总结

AC自动机算法总结  No.1 What's Aho-Corasick automaton? 一种多模式串匹配算法,该算法在1975年产生于贝尔实验室,是著名的多模匹配算法之一. 简单的说,KMP用来匹配一个模式串:但如果现在有多个模式串需要在同一篇文章中出现,现在就需要Aho-Corasick automaton算法了. 不要天真的以为AC自动机为auto-Accept,虽然他能让你AC一些题. No.2 My Understanding About Aho-Corasick automato