zoukankan      html  css  js  c++  java
  • Manacher-马拉车算法

    Manacher

    马拉车算法就是求解最长回文串

    并且将时间复杂度降到了O(n),

    它的原理就是将原始字符串进行了处理,在每一个字符的左右两边都加上特殊字符,让字符串变成一个奇回文

    然后通过数组储存标记,详细看这篇https://www.jianshu.com/p/392172762e55

    回文自动机

    回文树,也叫回文自动机

    类似AC自动机的一种回文串匹配自动机,也就是一棵字符树。同样类似AC自动机的是,每一个节点都有一个fail指针,fail指针指向的点表示当前串后缀中的最长回文串。

    A - The Number of Palindromes

     

    Now, you are given a string S. We want to know how many distinct substring of S which is palindrome.

    InputThe first line of the input contains a single integer T(T<=20), which indicates number of test cases.
    Each test case consists of a string S, whose length is less than 100000 and only contains lowercase letters.
    OutputFor every test case, you should output "Case #k:" first in a single line, where k indicates the case number and starts at 1. Then output the number of distinct substring of S which is palindrome.
    Sample Input

    3
    aaaa
    abab
    abcd

    Sample Output

    Case #1: 4
    Case #2: 4
    Case #3: 4

    因为回文自动机中每个新建的结点就表示一个回文子串,各个结点都不相同
    所以不同回文子串个数就是回文自动机中新增结点个数,直接输出即可

    #include<iostream>
    using namespace std;
    const int maxn=100010;
    const int ma=26;
    typedef long long ll;
    struct node
    {
        int next[maxn][ma];//和字典树的next指针类似 
        int fail[maxn];//失配后指向fail指针 
        ll cnt[maxn];
        int num[maxn];
        int len[maxn];//回文串长度 
        int s[maxn];//字符 
        int last;
        int n,p;//添加的字符个数,节点个数
        int newnode(int l)
        {
            for(int i=0;i<ma;i++)
               next[p][i]=0;
            cnt[p]=0;
            num[p]=0;
            len[p]=l;
            return p++;
        }
        void init()//初始化 
        {
            p=0;
            newnode(0);
            newnode(-1);
            last=0;
            n=0;
            s[n]=-1;
            fail[0]=1;
         } 
        int gfail(int x)//找最长 
        {
            while(s[n-len[x]-1]!=s[n])
               x=fail[x];
            return x;
        }
        void add(int c)
        {
            c-='a';
            s[++n]=c;
            int cu=gfail(last);//找匹配位置 
            if(!next[cu][c])
            {
                int now=newnode(len[cu]+2);//新建节点 
                fail[now]=next[gfail(fail[cu])][c];
                next[cu][c]=now;
                num[now] = num[fail[now]] + 1 ;//AC自动化及同款指针 
            }
            last=next[cu][c];
            cnt[last]++;
        }
        void count()
        {
            for(int i=p-1;i>=0;i--)
              cnt[fail[i]]+=cnt[i];
        }
    }tree;
    int main()
    {
        string a;
        std::ios::sync_with_stdio(false);
        int t;
        int m=1;
        cin>>t;
        while(t--)
        {
            cin>>a;
            tree.init();
            int len=a.size();
            for(int i=0;i<len;i++)
            {
                tree.add(a[i]);
            }
            cout<<"Case #"<<m++<<": ";
            cout<<tree.p-2<<endl;
        }
        return 0;
     } 
  • 相关阅读:
    CF185D Visit of the Great 解题报告
    CF1468M Similar Sets 解题报告
    CFgym102439 做题记录
    CF1187F Expected Square Beauty 解题报告
    CFgym103202 做题记录
    搜索学习笔记
    小甲鱼Python第019讲函数:灵活即强大 | 课后测试题及参考答案
    小甲鱼Python第018讲函数:灵活即强大 | 课后测试题及参考答案
    小甲鱼Python第017讲函数
    小甲鱼Python第016讲序列!序列!| 课后测试题及参考答案
  • 原文地址:https://www.cnblogs.com/ylrwj/p/11587093.html
Copyright © 2011-2022 走看看