ATP 和淡水工厂(factory)

时间限制:2s 空间限制:512MB
Background
在南极旅游的过程中 ATP意识到南极地区有丰富的淡水资源, 于是决定在南极建立淡水工厂,
向全世界供应冰冰凉的淡水来赚大钱!
它成功地说服了 zyf2000 和 cloverhxy 作为投资人, 很快一家规模宏大的工厂就轰隆隆地开工
了。工厂雇佣彩色的北极熊作为工人(工熊) ,利用北极熊锋利的牙齿把冰山啃下来,装在
瓶子里运到世界各地。
正在 ATP 的生意越做越大的时候,突然有一个自称税务官的亚马孙土著人来到了南极要对
ATP收税!可是 ATP 工厂的收益都买吃的了!怎么办!这个时候 zyf2000 想出了办法……
zyf2000 在参观工厂的时候发现,北极熊们皮毛的颜色种类如果细分下去还真是多!比如绿
色北极熊就有淡绿,草绿,墨绿和原谅绿多种。大约有 26 种不同的颜色。ATP 它们决定让
每只工熊剪下一点柔软的毛,给不习惯寒冷的税务官做一条长长的围巾!税务官拿到围巾以
后很感动,同意宽限一些缴税的时日。同时,他对这条围巾产生了兴趣……
Description
这条围巾的颜色分布可以描述为一个长度为 n 的只包含字母 A..Z 的字符串。税务官想知道
的问题很简单,他定义颜色串 S 的一个 goodstr为既是 S 的前缀也是 S 的后缀的字符串。对
于 S 的所有 goodstr,他想知道它们的长度分别是多少,以及它在 S 中分别出现了几次。
Input
只有一行一个仅由大写字母构成的字符串 S。
Output
第一行一个数 k代表 S 串的 goodstr个数;
接下来 k行,每行两个数字 a 和 b 描述一个 goodstr,a 代表它的长度,b代表它在 S 中的出
现次数。要求按照 a为关键字从小到大输出。显然每个不同的 goodstr的 a 值互不相同。
注意:goodstr包括这个字符串本身。

Sample Input
ABACABA

Sample Output
3
1 4
3 2
7 1

分析:
学姐的hu测题
学姐:真·送分题

这道题我一看
KMP+AC自动机
结果T三个点

正解:KMP+DP?(乱搞)
首先求出一个准确的t数组
(我一般喜欢用t,就是KMP数组,无所谓叫什么啦)
之后有一个递推式可以计算出答案
我们从字符串的最后向前统计答案
cnt[t[i]]+=cnt[i]
解释一下:
因为t中记录的都是当前最长的前缀及后缀,
所以某串的前后一定是一样的,
这就像一个简陋版的AC自动机,
只要长串出现过,那么ta的失配一定出现过

这里写代码片
#include<cstdio>
#include<iostream>
#include<cstring>

using namespace std;

const int N=100005;
int t[N];
int ch[N][27],len,tot=0;
char s[N];
int word[N],cnt[N],tt;

void doit()
{
    int i,j;
    len=strlen(s);
    t[0]=-1;
    for (i=0;i<len;i++)
    {
        int x=t[i];
        while (x!=-1&&s[i]!=s[x]) x=t[x];
        t[i+1]=++x;
        cnt[i]=1;
    }
    cnt[len]=1;
    return;
}

void solve()
{
    int i,j,now=0;
    for (i=len;i>=0;i--)
        cnt[t[i]]+=cnt[i];
    int f=t[len];
    while (f)
    {
        word[++word[0]]=f;
        f=t[f];
    }
    printf("%d
",word[0]+1);
    for (i=word[0];i>=1;i--)
        printf("%d %d
",word[i],cnt[word[i]]);
    printf("%d 1",len);
    return;
}

int main()
{
    freopen("factory.in","r",stdin);  
    freopen("factory.out","w",stdout);
    scanf("%s",&s);
    doit();
    solve();
    return 0;
}
原文地址:https://www.cnblogs.com/wutongtong3117/p/7673421.html