Gym - 101981M:(南京) Mediocre String Problem(回文树+exkmp)

#include<bits/stdc++.h>
#define ll long long
#define rep(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
const int maxn=1000010;
char S[maxn],T[maxn];
struct PT
{
    struct in{
        int dep,fail,len,son[26];
    }p[maxn];
    int cnt,last;
    void init()
    {
        //memset(p,0,sizeof(p));
        cnt=last=1;p[0].dep=p[1].dep=0;
        p[0].fail=p[1].fail=1;
        p[0].len=0; p[1].len=-1;
    }
    int add(int c,int n)
    {
        int np=last;
        while(S[n]!=S[n-1-p[np].len]) np=p[np].fail;
        if(!p[np].son[c]){
            int v=++cnt,k=p[np].fail; p[v].len=p[np].len+2;
            while(S[n]!=S[n-p[k].len-1]) k=p[k].fail;
            p[v].fail=p[k].son[c];
            p[np].son[c]=v; //这一句放前面会出现矛盾,因为np可能=k
            p[v].dep=p[p[v].fail].dep+1;
        }
        last=p[np].son[c];
        return p[last].dep;
    }
}Tree;
int N,M,num[maxn],Next[maxn],extand[maxn]; ll ans;
void getnext(){// next[i]: 以第i位置开始的子串与T的公共前缀长度
     int i,length=strlen(T+1);
     Next[1]=length;
     for(i=0;i+1<length&&T[i+1]==T[i+2];i++);
     Next[2]=i;
     int a=2;   //!
     for(int k=3;k<=length;k++){//长度+1,位置-1。
          int p=a+Next[a]-1, L=Next[k-a+1];
          if(L>=p-k+1){
              int j=(p-k+1)>0?(p-k+1):0;//中断后可能是负的
              while(k+j<=length&&T[k+j]==T[j+1]) j++;// 枚举(p+1,length) 与(p-k+1,length) 区间比较
              Next[k]=j, a=k;
          }
          else Next[k]=L;
    }
}
void getextand(){
    memset(Next,0,sizeof(Next));
    getnext();
    int Slen=strlen(S+1),Tlen=strlen(T+1),a=0;
    int MinLen=Slen>Tlen?Tlen:Slen;
    while(a<MinLen&&S[a+1]==T[a+1]) a++;
    extand[1]=a; a=1;
    for(int k=2;k<=Slen;k++){
        int p=a+extand[a]-1,L=Next[k-a+1];
        if(L>=p-k+1){
            int j=(p-k+1)>0?(p-k+1):0;
            while(k+j<=Slen&&j+1<=Tlen&&S[k+j]==T[j+1]) j++;
            extand[k]=j;a=k;
        }
        else extand[k]=L;
    }
}
int main()
{
    scanf("%s%s",S+1,T+1);
    N=strlen(S+1); M=strlen(T+1);
    reverse(S+1,S+N+1); Tree.init();
    rep(i,1,N) num[i]=Tree.add(S[i]-‘a‘,i);
    getextand();
    rep(i,1,N) ans+=(ll)num[i-1]*extand[i];
    printf("%lld\n",ans);
    return 0;
}

原文地址:https://www.cnblogs.com/hua-dong/p/10400366.html

时间: 2024-07-30 03:06:33

Gym - 101981M:(南京) Mediocre String Problem(回文树+exkmp)的相关文章

【HDU5421】Victor and String(回文树)

[HDU5421]Victor and String(回文树) 题面 Vjudge 大意: 你需要支持以下操作: 动态在前端插入一个字符 动态在后端插入一个字符 回答当前本质不同的回文串个数 回答当前回文串个数 题解 回文树前端插入的操作,学一学感觉并不难? 额外维护一下一个前端插入的\(last\) 然后就和后端插入一模一样,前端插入时就是前端插入的\(last\) 唯一会产生的影响的就是当前字符差完后, 发现现在的\(last\)就是整个串,那么就要更新另外一端的\(last\)为当前这一端

2018南京网络赛 - Skr 回文树

题意:求本质不同的回文串(大整数)的数字和 由回文树的性质可知贡献只在首次进入某个新节点时产生 那么只需由pos和len算出距离把左边右边删掉再算好base重复\(O(n)\)次即可 位移那段写的略微凌乱.. #include<bits/stdc++.h> #define rep(i,j,k) for(int i=j;i<=k;i++) #define rrep(i,j,k) for(int i=j;i>=k;i--) #define println(a) printf("

HDU - 5157 :Harry and magic string (回文树)

Sample Input aca aaaa Sample Output 3 15 题意: 多组输入,每次给定字符串S(|S|<1e5),求多少对不相交的回文串. 思路:可以用回文树求出以每个位置结尾的回文串数,那么累加得到前缀和: 倒着再做一遍得到每个位置为开头的回文串数,乘正向求出的前缀和即可. #include<bits/stdc++.h> #define ll long long #define rep(i,a,b) for(int i=a;i<=b;i++) #define

HDU - 5421:Victor and String (回文树,支持首尾插入新字符)

Sample Input 6 1 a 1 b 2 a 2 c 3 4 8 1 a 2 a 2 a 1 a 3 1 b 3 4 Sample Output 4 5 4 5 11 题意:多组输入,开始字符串为空,支持4中操作: 1,在字符串首加字符: 2,在字符串尾加字符: 3,查询字符串不同本质的回文串个数: 4,查询回文串个数总和 思路:因为支持首尾加入,所以和常规的回文树有些不同. 参考了YYB的博客. 发现首尾互相影响,当且仅当整个字符串是回文串. 其他情况两头正常加即可. #include

HDU 5157 Harry and magic string(回文树)

Harry and magic string Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 223    Accepted Submission(s): 110 Problem Description Harry got a string T, he wanted to know the number of T's disjoint

HDU 6599 I Love Palindrome String (回文树+hash)

题意 找如下子串的个数: (l,r)是回文串,并且(l,(l+r)/2)也是回文串 思路 本来写了个回文树+dfs+hash,由于用了map所以T了 后来发现既然该子串和该子串的前半部分都是回文串,所以该子串的前半部分和后半部分是本质相同的! 于是这个log就去掉了 代码 #include<iostream> #include<cstdio> #include<algorithm> #include<cmath> #include<cstring>

Mediocre String Problem

问题 M: Mediocre String Problem 时间限制: 1 Sec  内存限制: 128 MB提交: 18  解决: 4[提交] [状态] [命题人:admin] 题目描述 Given two strings s and t, count the number of tuples (i, j, k) such that1. 1 ≤ i ≤ j ≤ |s|2. 1 ≤ k ≤ |t|.3. j − i + 1 > k.4. The i-th character of s to th

计蒜客 2018南京网络赛 I Skr ( 回文树 )

题目链接 题意 : 给出一个由数字组成的字符串.然后要你找出其所有本质不同的回文子串.然后将这些回文子串转化为整数后相加.问你最后的结果是多少.答案模 1e9+7 分析 : 应该可以算是回文树挺裸的题目吧 可惜网络赛的时候不会啊.看着马拉车想半天.卒... 对于每一个节点.记录其转化为整数之后的值 然后在回文串插入字符的时候 不断维护这个信息就行了 其实很好理解.看一下代码就懂了 ( 如果你学过回文树的话... ) 就是多加了变量 val .维护语句 #include<bits/stdc++.h

poj3974 最长回文串 exkmp

Palindrome Time Limit: 15000MS   Memory Limit: 65536K Total Submissions: 3695   Accepted: 1338 Description Andy the smart computer science student was attending an algorithms class when the professor asked the students a simple question, "Can you pro