比赛 NOIP模拟赛by mzx Day2 评测结果 WWWWWWWTTT
题目名称 拯救紫萱学姐 最终得分 0
用户昵称 sxysxy 运行时间 5.131 s
代码语言 C++ 内存使用 230.15 MiB
提交时间 2016-10-20 21:07:08
显示代码纯文本
#include <cstdio>
#include <cstdlib>
#include <cstdarg>
#include <iostream>
#include <queue>
#include <string>
#include <cstring>
#include <vector>
#include <cctype>
using namespace std;
#define MAXN 1000001
class SAM
{
    int last, size;
public:
    struct state
    {
        int link;
        int len;
        int next[26];
        void init()
        {
            len = 0;
            link = -1;
            memset(next, 0, sizeof(next));
        }
    }st[MAXN<<1];
    int rec[MAXN<<1];
    SAM()
    {
        last = size = 0;
        newst();
    }
    int newst()
    {
        st[size++].init();
        return size-1;
    }
    int expand(int c)
    {
        int cur = newst();
        st[cur].len = st[last].len+1;
        int p;
        for(p = last; ~p && !st[p].next[c]; p = st[p].link)
            st[p].next[c] = cur;
        if(p == -1)
            st[cur].link = 0;
        else
        {
            int q = st[p].next[c];
            if(st[q].len == st[p].len+1)
                st[cur].link = q;
            else
            {
                int clone = newst();
                memcpy(st[clone].next, st[q].next, sizeof(st[q].next));
                st[clone].len = st[p].len+1;
                st[clone].link = st[q].link;
                for(; ~p && st[p].next[c] == q; p = st[p].link)
                    st[p].next[c] = clone;
                st[q].link = st[cur].link = clone;
            }
        }
        return last = cur;
    }
}sam;
int read_string(char *s)
{
    int len = 1;
    char c;
    while(!isalpha(c = getchar()));
    s[0] = c;
    while(isalpha(c = getchar()))s[len++] = c;
    s[len] = 0;
    return len;
}
typedef long long LL;
char str[MAXN];
LL comm[MAXN];
int main()
{
    freopen("savemzx.in", "r", stdin);
    freopen("savemzx.out", "w", stdout);
    int len = read_string(str);
    int s = 0;   //前缀状态指针
    int match = 0;
    for(int i = 1; i <= len; i++)
    {
        comm[i] = 0;  //最开始认为没有公共部分
        int c = str[i-1]-'a'; 
        int t = sam.expand(c);    //加入字符构成的状态节点
        if(sam.st[t].link || i == 1)   //之前出现过这个字符/开头字符
        {
            while(~t && sam.st[t].len != sam.st[s].len+1)
                t = sam.st[t].link;
            if(~t)
            {
                s = sam.st[s].next[c];
                match = sam.st[t].len;
            }
        }else
        {
            s = 0;
            match = 0;
        }
        comm[i] = match;
    }
    LL ans = 0;
    for(int i = 1; i <= len; i++)
    {
        for(int j = i+1; j <= len; j++)
        {
            LL cnt = 0;
            int a = i;
            int b = j;
            while(a)
            {
                cnt += (a-comm[a])*(a-comm[a]);
                if(a == comm[a])
                {
                    cnt += a*a;
                    break;
                }
                a = comm[a];
            }
            while(b)
            {
                cnt += (b-comm[b])*(b-comm[b]);
                if(b == comm[b])
                {
                    cnt += b*b;
                    break;
                }
                b = comm[b];
            }
            ans = max(ans, cnt);
        }
    }
    printf("%lld\n", ans);
    return 0;
}