12
22
2015
0

【JSOI2015】字符串生成器

首先[tex]\sqrt n[/tex]枚举答案长度,在n枚举起点。接下来就是验证是否可行了。一开始想了一个错误的贪心,还自以为能A。。。

其实我们可以用区间DP来判断。

首先我们定义一下完美匹配。区间[i,j]是完美匹配当且仅当在用最优的方法删去一些模式串后,剩余的是模式串的前缀。显然如果区间长度是模式串的长度倍数又是完美匹配,那就符合条件。

完美匹配可以这样转移,将[i,j]分为[i,k],[k+1,j]只要两段都是完美匹配且至少有一段的长度是区间长度的倍数,这是一种转移。

还有一种转移是,[i,j-1]是完美匹配,且j处的字符为[i,j-1]的前缀的下一位,也就是模式串的第((j-i)%len+1)位,len是模式串的长度。

这样转移是l/len的复杂度的,加点乱七八糟的优化就能过了。

代码:

 

#include<set>
#include<cstdio>
#include<string>
#include<cstring>
using namespace std;
int T,l,ans;
int f[210][210];
set<string> st;
char s[510],str[510];
int compare(int x,int len)
{
    for (int i=0;i<len;i++)
        if (s[i+x]>str[i]) return 1;else
        if (s[i+x]<str[i]) return -1;
    return 0;
}
void judge(int len)
{
    if (len>ans) return;
    for (int L=0;L<l;L++)
    if (L+len-1==l) break;else
    if (s[L]==s[0]&&s[L+len-1]==s[l-1])
    {
        string s1;
        s1.clear();
        for (int i=0;i<len;i++)
            s1+=s[L+i];
        if (st.count(s1)) continue;
        st.insert(s1);
        memset(f,0,sizeof(f));
        for (int i=0;i<l;i++) if (s[i]==s[L]) f[i][i]=1;
        for (int p=2;p<=l;p++)
            for (int i=0;i<l-p+1;i++)
            {
                int j=i+p-1;
                f[i][j]|=f[i][j-1]&(s[L+(p-1)%len]==s[j]);
                if (f[i][j]) continue;
                for (int k=1;k<=p/len;k++)
                {
                    f[i][j]|=f[i][i+k*len-1]&f[i+k*len][j];
                    f[i][j]|=f[j-k*len+1][j]&f[i][j-k*len];
                    if (f[i][j]) break;
                }
            }
        if (f[0][l-1])
        {
            if ((len<ans)||(len==ans&&(compare(L,len)<0)))
            {
                ans=len;
                for (int i=0;i<len;i++)
                    str[i]=s[L+i];
            }
        }
    }
}
int main()
{
    scanf("%d",&T);
    while (T--)
    {
        scanf("%s",s);
        l=strlen(s);
        ans=l+1;
        st.clear();
        for (int i=1;i*i<=l;i++)
        if (l%i==0)
        {
            judge(i);
            if (i*i!=l) judge(l/i);
        }
        for (int i=0;i<ans;i++)
            printf("%c",str[i]);
        printf("\n");
    }
}
Category: Dynamic Programming | Tags: | Read Count: 265

登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter

Host by is-Programmer.com | Power by Chito 1.3.3 beta | Theme: Aeros 2.0 by TheBuckmaker.com