CF 1200E HASH模板

一道字符串题,从前往后压缩句子

每次可以把已有的后缀与带添加的前缀相同的部分压缩掉,问最短压缩后的句子

 

显然这道题就是要做一个字符串匹配的工作,所以Kmp肯定可以做,但是后来看了一下好像会被卡常数,还是要稍微优化一点的,

这里因为在练hash,所以就用hash做了。

这里我们要的是l,r的哈希值,而且要O(1)获得,不能每次重做,所以就用类似前缀和的思想,开两个数组差分一下就可以(大概是叫这个?)

然后冲浪的时候发现一个很好的板子,正好用上测一下,还可以适用于多哈希。

 

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cstring>
 4 using namespace std;
 5 const int maxn=1000005;
 6 struct Hash{
 7     int base[4],mod[4];
 8     int tot,hash[4][maxn],pw[4][maxn]; //字符串长度,hash:记从1~i的hash值,pw:记录base^i
 9     Hash() {
10         tot=0;
11         for(int i=1;i<=3;i++) pw[i][0]=1;
12         base[1]=233;base[2]=19260817;base[3]=20030714;
13         mod[1]=1e9+7;mod[2]=1e9+9;mod[3]=998244353;
14     }
15 
16     void init() {
17         tot=0;
18     }
19     void insert(int c) {
20         tot++;
21         for(int i=1;i<=3;i++) hash[i][tot]=(1LL*hash[i][tot-1]*base[i]+c)%mod[i];
22         for(int i=1;i<=3;i++) pw[i][tot]=(1LL*pw[i][tot-1]*base[i])%mod[i];
23     }
24     //字符串[l,r]hash值,type为第几个hash
25     int query(int l,int r,int type) { 
26         return (hash[type][r]-(1LL*hash[type][l-1]*pw[type][r-l+1]%mod[type])+mod[type])%mod[type];
27     }
28     //判断字符串u的[lu,ru]内的字符串和字符串v的[lv,rv]内的字符串是否相同
29     friend bool same(Hash &u,int lu,int ru,Hash &v,int lv,int rv) { 
30         if(ru-lu!=rv-lv) return false;
31         for(int i=1;i<=3;i++) if(u.query(lu,ru,i)!=v.query(lv,rv,i)) return false;
32         return true;
33     }
34 }h1,h2;
35 int n;
36 char s[1000005],res[1000005];
37 int main(){
38     h1.init();
39     scanf("%d",&n);
40     int len=0;
41     for (int i=1; i<=n; i++){
42         scanf("%s",s+1);
43         int l=strlen(s+1);
44         if (i==1){
45             for (int j=1; j<=l; j++){
46                 h1.insert(s[j]);
47                 res[j]=s[j];
48             }
49             len=l;
50         }
51         else {
52             int p=0;
53             h2.init();
54             for (int j=1; j<=l; j++){
55                 h2.insert(s[j]);
56                 if (same(h1,max(1,h1.tot-j+1),h1.tot,h2,1,h2.tot)) p=j;
57             }
58             for (int j=p+1; j<=l; j++){
59                 h1.insert(s[j]);
60                 res[++len]=s[j];
61             }
62         }
63     }
64     for (int i=1; i<=len; i++)
65         printf("%c",res[i]);    
66 }
View Code

 

posted @ 2020-11-25 15:57  我是菜狗QAQ  阅读(153)  评论(0编辑  收藏  举报