白兔的字符串(字符串hash+模拟map)

链接:https://ac.nowcoder.com/acm/problem/15253

题目描述

白兔有一个字符串T。白云有若干个字符串S1,S2..Sn

白兔想知道,对于白云的每一个字符串,它有多少个子串是和T循环同构的。

提示:对于一个字符串a,每次把a的第一个字符移动到最后一个,如果操作若干次后能够得到字符串b,则a和b循环同构。

所有字符都是小写英文字母

输入描述:

第一行一个字符串T(|T|<=10^6)第二行一个正整数n (n<=1000)接下来n行为S1~Sn (|S1|+|S2|+…+|Sn|<=10^7),max(|S1|,|S2|,|S3|,|S4|,..|Sn|)<=10^6

具体思路:

首先把字符串T放大一倍,这样就能找到所有的T的长度为len的情况了。然后hash一遍,标记一下。

然后对于输入的T个字符串,处理他的每个长度为len的子串,看是否被标记过。

(map会超时,可以模拟map)

AC代码:

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 # define ll long long
 4 # define ull unsigned long long
 5 const int mod = 1e9+7;
 6 const int maxn = 1e6+100;
 7 const ull base = 131;
 8 const int mod_map = 14937;
 9 char str1[maxn],str2[maxn];
10 ull ind[maxn],hash1[maxn],hash2[maxn];
11 void init1()
12 {
13     ind[0]=1ll;
14     for(int i=1; i<maxn; i++)
15     {
16         ind[i]=ind[i-1]*base;
17     }
18 }
19 struct node
20 {
21     ull to;
22     int nex;
23 } edge[maxn];
24 int  head[maxn],cnt;
25 void addedge(ull x)// 类似于一个映射
26 {
27     int pos=x%mod_map;
28     edge[cnt].to=x;
29     edge[cnt].nex=head[pos];
30     head[pos]=cnt++;
31 }
32 int Find(ull x)
33 {
34     int pos=x%mod_map;
35     for(int i=head[pos]; i!=-1; i=edge[i].nex)
36     {
37         if(edge[i].to==x)
38             return 1;
39     }
40     return 0;
41 }
42 ull get_sub1(int l,int r)
43 {
44     return hash1[r]-hash1[l-1]*ind[r-l+1];
45 }
46 ull get_sub2(int l,int r)
47 {
48     return hash2[r]-hash2[l-1]*ind[r-l+1];
49 }
50 void init2()
51 {
52     int len=strlen(str1+1);
53     hash1[0]=0;
54     for(int i=len+1; i<=len+len; i++)
55     {
56         str1[i]=str1[i-len];
57     }
58     for(int i=1; i<=len+len; i++)
59     {
60         hash1[i]=hash1[i-1]*base+(ull)(str1[i]);
61         if(i>=len)
62         {
63             ull tmp=get_sub1(i-len+1,i);
64             addedge(tmp);
65         }
66     }
67 }
68 int main()
69 {
70     memset(head,-1,sizeof(head));
71     init1();
72     scanf("%s",str1+1);
73     int len1=strlen(str1+1);
74     init2();
75     int T;
76     scanf("%d",&T);
77     while(T--)
78     {
79         int ans=0;
80         scanf("%s",str2+1);
81         int  len2=strlen(str2+1);
82         for(int i=1; i<=len2; i++)
83         {
84             hash2[i]=hash2[i-1]*base+(ull)(str2[i]);
85             if(i>=len1)
86                 if(Find(get_sub2(i-len1+1,i)))
87                     ans++;
88         }
89         printf("%d\n",ans);
90     }
91     return 0;
92 }

 

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 # define ll long long
 4 # define ull unsigned long long
 5 //# define ull (unsigned long long)
 6 const int maxn = 2e6+100;
 7 const int mod_map = 14937;
 8 const ull base = 131;
 9 ull ind[maxn];
10 ull hash1[maxn],hash2[maxn];
11 char str[maxn];
12 vector<ull>Edge[maxn];
13 void add(ull t)
14 {
15     ull tmp=t%mod_map;
16     Edge[tmp].push_back(t);
17 }
18 ull getsub1(int l,int r)
19 {
20 return hash1[r]-hash1[l-1]*ind[r-l+1];
21 }
22 ull getsub2(int l,int r)
23 {
24 return hash2[r]-hash2[l-1]*ind[r-l+1];
25 }
26 bool Find(ull tmp)
27 {
28     ull pos=tmp%mod_map;
29     for(int i=Edge[pos].size()-1; i>=0; i--)
30     {
31         if(Edge[pos][i]==tmp)
32             return true;
33     }
34     return false;
35 }
36 void init()
37 {
38     ind[0]=1ll;
39     for(int i=1; i<maxn; i++)
40     {
41         ind[i]=ind[i-1]*base;
42     }
43     int len=strlen(str+1);
44     for(int i=1+len; i<=len+len; i++)
45     {
46         str[i]=str[i-len];
47     }
48     for(int i=1; i<=len+len; i++)
49     {
50         hash1[i]=hash1[i-1]*base+(ull)(str[i]);
51         if(i>=len)
52         {
53             add(getsub1(i-len+1,i));
54         }
55     }
56 }
57 int main()
58 {
59     scanf("%s",str+1);
60     int tmp=strlen(str+1);
61     init();
62     int T;
63     scanf("%d",&T);
64     while(T--)
65     {
66         scanf("%s",str+1);
67         int len=strlen(str+1);
68         int ans=0;
69         for(int i=1; i<=len; i++)
70         {
71             hash2[i]=hash2[i-1]*base+(ull)(str[i]);
72             if(i>=tmp)
73             {
74                 if(Find(getsub2(i-tmp+1,i)))
75                     ans++;
76             }
77         }
78         printf("%d\n",ans);
79     }
80     return 0;
81 }
vector版

 

posted @ 2019-05-16 21:09  Let_Life_Stop  阅读(404)  评论(0编辑  收藏  举报