首先是几份模版

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\n",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] = '\0';
       // printf("%s %s\n",S,T);
        ekmp(S,len,T,len,fail,ext1);
        ekmp(T,len,S,len,fail,ext2);
       // for (int i = 0 ; i <= len ; i++) printf("%d ",ext1[i]); puts("");
        //for (int i = 0 ; i <= len ; i++) printf("%d ",ext2[i]); puts("");
        //for (int i = 0 ; i <= len ; i++) printf("%d ",sum[i]); puts("");
        int ret = 0;
        for (int i = 0 ; i < len ; i++)
        {
            if (i > 0 && ext1[i] + i == len)
            {
                int pos = ext1[i];
                int res = sum[pos];
               // printf("%d %d\n",i,res);
                if (ext2[pos] + pos == len)
                {
                    res += sum[len] - sum[pos];
                }
               // printf("%d %d\n",i,res);
                ret = max(res,ret);
            }
            else
            {
                int pos = i + 1;
                int res = 0;
                if (ext2[pos] + pos == len)
                    res += sum[len] - sum[pos];
                ret = max(ret,res);
            }
        }
        printf("%d\n",ret);
    }
    return 0;
}
View Code

相关文章: