首先是几份模版
KMP
void kmp_pre(char x[],int m,int fail[]) { int i,j; j = fail[0] = -1; i = 0; while (i < m) { while (j != -1 && x[i] != x[j]) j = fail[j]; fail[++i] = ++j; } } int kmp_count(char x[],int m,char y[],int n) { int i = 0,j = 0; int ans = 0; while (i < n) { while (j != -1 && y[i] != x[j]) j = fail[j]; i++;j++; if (j >= m) { ans++; j = fail[j]; } } return ans; }
最小表示法 。资料http://blog.csdn.net/acm_cxlove/article/details/7909087
HDU 3374 String problem
#include <map> #include <set> #include <list> #include <cmath> #include <ctime> #include <deque> #include <stack> #include <queue> #include <cctype> #include <cstdio> #include <string> #include <vector> #include <climits> #include <cstdlib> #include <cstring> #include <iostream> #include <algorithm> #define LL long long #define PI 3.1415926535897932626 using namespace std; int gcd(int a, int b) {return a % b == 0 ? b : gcd(b, a % b);} const int MAXN = 1000010; char str[MAXN]; int fail[MAXN]; void kmp_pre(char x[],int m,int fail[]) { int i = 0,j; j = fail[0] = -1; while (i < m) { while (j != -1 && x[i] != x[j]) j = fail[j]; fail[++i] = ++j; } } int getval(char * str,int len,bool type) { int i = 0,j = 1,k = 0; while (i < len && j < len && k < len) { int val = str[(j + k) % len] - str[(i + k) % len]; if (val == 0) k++; else { if (type) { if (val > 0) j += k + 1; else i += k + 1; } else { if (val > 0) i += k + 1; else j += k + 1; } k = 0; if (i == j) j++; } } return min(i,j); } int main() { while (scanf("%s",str) != EOF) { int len = strlen(str); kmp_pre(str,len,fail); int l = getval(str,len,true); int r = getval(str,len,false); int ret = len % (len - fail[len]) ? 1 : len / (len - fail[len]); printf("%d %d %d %d ",l + 1,ret,r + 1,ret); } return 0; }
扩展KMP 学习资料http://wenku.baidu.com/link?url=oRb889beOwu3N4gZHJ0W3o91I78GpCqjIGdOmfPIp3WD5GxCHdc3njCXu0ocgDKTSNaBG_deOWszmrVFZMrbTiureG3otYc522XrJcqdbry
模版1:
HDU 3613 BestReward
将一个串分成2段,如果一段不是回文串,那么权值为0,否则为按照对应法则的权值
权值不是很难统计直接前缀和
这里用扩展KMP来判断回文串,将原串反转得到T,那么由扩展KMP的定义,
判断前半段串如果是回文串的时候,就是以原串为模式传,反串为回文串,判断EXTEND[i] + i == len
后半段同理直接暴力
#include <map> #include <set> #include <list> #include <cmath> #include <ctime> #include <deque> #include <stack> #include <queue> #include <cctype> #include <cstdio> #include <string> #include <vector> #include <climits> #include <cstdlib> #include <cstring> #include <iostream> #include <algorithm> #define LL long long #define PI 3.1415926535897932626 using namespace std; int gcd(int a, int b) {return a % b == 0 ? b : gcd(b, a % b);} const int MAXN = 500010; const int INF = 0x3f3f3f3f; char S[MAXN],T[MAXN]; int fail[MAXN]; int ext1[MAXN],ext2[MAXN]; int val[30]; int sum[MAXN]; void pre_ekmp(char x[],int m,int fail[]) { fail[0] = m; int j = 0; while (j + 1 < m && x[j] == x[j + 1]) j++; fail[1] = j; int k = 1; for (int i = 2 ; i < m ; i++) { int p = fail[k] + k - 1; int L = fail[i - k]; if (i + L < p + 1) fail[i] = L; else { j = max(0,p - i + 1); while (i + j < m && x[i + j] == x[j]) j++; fail[i] = j; k = i; } } } void ekmp(char x[],int m,char y[],int n,int fail[],int extend[]) { pre_ekmp(x,m,fail); int j = 0; while (j < n && j < m && x[j] == y[j])j++; extend[0] = j; int k = 0; for (int i = 1 ; i < n ; i++) { int p = extend[k] + k - 1; int L = fail[i - k]; if (i + L < p + 1) extend[i] = L; else { j = max(0,p - i + 1); while (i + j < n && j < m && y[i + j] == x[j]) j++; extend[i] = j; k = i; } } } int main() { int kase; scanf("%d",&kase); while (kase--) { for (int i = 0 ; i < 26 ; i++) scanf("%d",&val[i]); scanf("%s",S); memset(sum,0,sizeof(sum)); int len = strlen(S); for (int i = 0 ; i < len ; i++) sum[i + 1] = sum[i] + val[S[i] - 'a']; for (int j = len - 1,i = 0 ; j >= 0 ;j--,i++) T[i] = S[j]; T[len] = '