UVAlive6439_Pasti Pas!

题目是说给你一个字符串,现在要你用一些特殊的符号代替这个字符串中某一些子串,使得被替换后的串是一个回文串。

现在要你求替换后的字符串的最大的可能的长度。

其实这个题目没有什么固定的算法哦,我直接暴力就过了,但是中间手滑,wa了太多发。

其实可以这样来考虑,我们这个字符串的反序也保存一遍,这样可以建立起一个类似于链表的结构(对于每一个字符,我们在这里指向它下一次出现的下标)

这样如果最后可以被替换为n个串,那么一定存在x1,x2,……,xn,是的1-x1,x1-x2,……xn-1-xn是完美的反向匹配的。

同时我们需要维护每一个x最小,这样就一定是最小的。

虽然可能出现极限数据使得复杂度为n^2,但是……(可能卡到n方吗?)

#include <iostream>
#include <cstdio>
#include <cstring>
#define maxn 100100
using namespace std;

int next[3][maxn][26];
char s[3][maxn];
int n,m,k,t,pos[26],ans,cas=0;

void init_Z(int x)
{
    memset(pos,0x3f,sizeof pos);
    for (int i=n; i>0; i--)
    {
        pos[s[x][i]-'A']=i;
        for (int j=0; j<26; j++)
            next[x][i][j]=pos[j];
    }
}

int match(int x)
{
    if (x>n/2)
    {
        if ((n&1) && x==n/2+1) return 1;
        else return 0;
    }
    int pos=max(next[1][x][s[2][x]-'A'],next[2][x][s[1][x]-'A']);
    while (1)
    {
        if (pos>n/2) return 1;
        bool flag=true;
        for (int i=0; i<pos-x+1; i++)
            if (s[1][x+i]!=s[2][pos-i])
            {
                flag=false;
                break;
            }
        if (flag)
            return 2+match(pos+1);
        else pos=max(next[1][pos+1][s[2][x]-'A'],next[2][pos+1][s[1][x]-'A']);
    }

}

int main()
{
    scanf("%d",&t);
    while (t--)
    {
        scanf("%s",s[1]+1);
        n=strlen(s[1]+1);
        for (int i=1; i<=n; i++) s[2][i]=s[1][n+1-i];
        init_Z(1); init_Z(2);
        ans=match(1);
        printf("Case #%d: %d
",++cas,ans);
    }
    return 0;
}
如有转载,请注明出处(http://www.cnblogs.com/lochan)
原文地址:https://www.cnblogs.com/lochan/p/3452815.html