标签:mem set 字符 alc typedef put bsp 情况 ref
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 4828 Accepted Submission(s): 1949
题意:
找到给定的字符串$S$的最小表示法和最大表示法。并且找到他在所有循环同构串中的出现次数。
思路:
首先肯定是要先分别找出最大表示法和最小表示法对应的起始下标。
方法就是先复制一倍接在后面,然后用两个指针分别从0和1开始往后扫描,在第一个发现不相等的位置比较$s[i+k]$和$s[j+k]$的大小。
然后用exKMP分别对最小表示法和最大表示法求$extend$数组。
然后数一下有多少个$extend[i] = n$,这就是个数。
1 #include<iostream> 2 #include<bits/stdc++.h> 3 #include<cstdio> 4 #include<cmath> 5 //#include<cstdlib> 6 #include<cstring> 7 #include<algorithm> 8 //#include<queue> 9 #include<vector> 10 //#include<set> 11 //#include<climits> 12 //#include<map> 13 using namespace std; 14 typedef long long LL; 15 #define N 100010 16 #define pi 3.1415926535 17 #define inf 0x3f3f3f3f 18 19 const int maxn = 1e6 + 6; 20 char s[maxn * 2], t[maxn]; 21 int nxt[maxn * 2], ex_min[maxn * 2], ex_max[maxn * 2]; 22 23 void GETNEXT(char *str) 24 { 25 int i=0,j,po,len=strlen(str); 26 nxt[0]=len;//初始化next[0] 27 while(str[i]==str[i+1]&&i+1<len)//计算next[1] 28 i++; 29 nxt[1]=i; 30 po=1;//初始化po的位置 31 for(i=2;i<len;i++) 32 { 33 if(nxt[i-po]+i<nxt[po]+po)//第一种情况,可以直接得到next[i]的值 34 nxt[i]=nxt[i-po]; 35 else//第二种情况,要继续匹配才能得到next[i]的值 36 { 37 j=nxt[po]+po-i; 38 if(j<0)j=0;//如果i>po+next[po],则要从头开始匹配 39 while(i+j<len&&str[j]==str[j+i])//计算next[i] 40 j++; 41 nxt[i]=j; 42 po=i;//更新po的位置 43 } 44 } 45 } 46 //计算extend数组 47 void EXKMP(char *s1,char *s2, int *ex) 48 { 49 int i=0,j,po,len=strlen(s1),l2=strlen(s2); 50 GETNEXT(s2);//计算子串的next数组 51 while(s1[i]==s2[i]&&i<l2&&i<len)//计算ex[0] 52 i++; 53 ex[0]=i; 54 po=0;//初始化po的位置 55 for(i=1;i<len;i++) 56 { 57 if(nxt[i-po]+i<ex[po]+po)//第一种情况,直接可以得到ex[i]的值 58 ex[i]=nxt[i-po]; 59 else//第二种情况,要继续匹配才能得到ex[i]的值 60 { 61 j=ex[po]+po-i; 62 if(j<0)j=0;//如果i>ex[po]+po则要从头开始匹配 63 while(i+j<len&&j<l2&&s1[j+i]==s2[j])//计算ex[i] 64 j++; 65 ex[i]=j; 66 po=i;//更新po的位置 67 } 68 } 69 } 70 71 int main() 72 { 73 while(scanf("%s", s) != EOF){ 74 int n = strlen(s); 75 for(int i = 0; i < n; i++)s[n + i] = s[i]; 76 int i = 0, j = 1, k; 77 while(i < n && j < n){ 78 for(k = 0; k < n && s[i + k] == s[j + k]; k++); 79 if(k == n)break; 80 if(s[i + k] > s[j + k]){ 81 i = i + k + 1; 82 if(i == j)i++; 83 } 84 else{ 85 j = j + k + 1; 86 if(i == j)j++; 87 } 88 } 89 int rnk_min = min(i, j); 90 91 i = 0, j = 1; 92 while(i < n && j < n){ 93 for(k = 0; k < n && s[i + k] == s[j + k]; k++); 94 if(k == n)break; 95 if(s[i + k] > s[j + k]){ 96 j = j + k + 1; 97 if(i == j)j++; 98 } 99 else{ 100 i = i + k + 1; 101 if(i == j)i++; 102 } 103 } 104 int rnk_max = min(i, j); 105 106 int min_cnt = 0; 107 memcpy(t, s + rnk_min, n); 108 EXKMP(s, t, ex_min); 109 for(int i = 0;i < n; i++){ 110 if(ex_min[i] == n)min_cnt++; 111 } 112 int max_cnt = 0; 113 memcpy(t, s + rnk_max, n); 114 EXKMP(s, t, ex_max); 115 for(int i = 0; i < n; i++){ 116 if(ex_max[i] == n)max_cnt++; 117 } 118 printf("%d %d %d %d\n", rnk_min + 1, min_cnt, rnk_max + 1, max_cnt); 119 } 120 return 0; 121 }
hdu3374 String Problem【最小表示法】【exKMP】
标签:mem set 字符 alc typedef put bsp 情况 ref
原文地址:https://www.cnblogs.com/wyboooo/p/9989294.html