LuoguP3121 [USACO15FEB]审查(黄金)Censoring (Gold)【Hash做法】By cellur925

题目传送门

其实这题正解是AC自动机的,字符串哈希吸氧才能过的,但是我太菜了不会...只能先用哈希苟了。


在扫描单词的时候首先把各个单词的哈希值和长度存起来。然后按照长度从小到大将各单词排序。而那个长长的字符串呢,我们就把它一点一点往栈里塞,够最小长度单词的长度时,我们就比较下,这样反复下去。如果遇到相同的字符串,就把他们弹出。

这个思路最巧妙的一点感觉就是用栈了。我自己写哈希的时候遇到删除的情况就布吉岛怎么搞了qwq。

这里的哈希值不能预处理出来的,而是动态维护的。因为有可能会删掉子串。所以只需要预处理出p数组(131的乘方),然后动态求哈希值。

Code

 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<cstring>
 4 #include<iostream>
 5 
 6 using namespace std;
 7 typedef unsigned long long ull;
 8 
 9 int lenall,top,n;
10 char sta[100090],tmp[100090],s[100090];
11 ull b=131,f[100090],p[100090];
12 struct dictionary{
13     int len;
14     ull has;
15 }t[2000];
16 
17 bool cmp(dictionary a,dictionary b)
18 {
19     return a.len<b.len;
20 }
21 
22 ull gethash(int l,int r)
23 {
24     return f[r]-f[l-1]*p[r-l+1];
25 }
26 
27 int main()
28 {
29     scanf("%s",sta+1);
30     p[0]=1;
31     lenall=strlen(sta+1);
32     scanf("%d",&n);
33     for(int i=1;i<=n;i++)
34     {
35         scanf("%s",tmp+1);
36         t[i].len=strlen(tmp+1);
37         for(int j=1;j<=t[i].len;j++)
38             t[i].has=t[i].has*b+(tmp[j]-'a'+1);
39     }
40     sort(t+1,t+1+n,cmp);
41     for(int i=1;i<=lenall;i++)
42         p[i]=p[i-1]*b;
43     for(int i=1;i<=lenall;i++)
44     {
45         s[++top]=sta[i];
46         f[top]=f[top-1]*b+s[top];
47         while(top<t[1].len&&i<lenall)
48             s[++top]=sta[++i],f[top]=f[top-1]*b+s[top];
49         for(int j=1;j<=n&&top;j++)
50             if(top-t[j].len+1>=1&&t[j].has==gethash(top-t[j].len+1,top))
51                 top-=t[j].len;
52     }
53     for(int i=1;i<=top;i++)
54         cout<<s[i]; 
55     cout<<endl;
56     return 0;
57 }
View Code

 

猜你喜欢

转载自www.cnblogs.com/nopartyfoucaodong/p/9768507.html