• Colorful String【回文串数量】


    题意:

    给定一个字符串,要求找出所有回文子串中不同字母的个数的总和。
    题目链接:https://nanti.jisuanke.com/t/41389

    分析:

    可以先利用 (Manacher) 求出以各个位置为中心的回文串的长度。关键在于如何求出一个回文串中不同字母的个数,根据回文串的性质,只需要求出一边即可。可以利用主席树,也可以先预处理出,每个位置前的各个字母最后出现的位置。计算时,只要判断该字母是否在回文串范围内,然后根据该位置离回文串的边界的距离来确定其贡献,累加求和。

    代码:

    //回文串
    // 算法第一步就是:预处理字符串,做法是在每一个字符的左右都加上一个特殊字符(前提是这个字符在字符串没有出现过)
    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int N = 3e5+5;
    char s[N]; //原始字符串
    char sn[N << 1]; //扩充后的新字符串
    int sen[N << 1];//表示以sn[i]为中心的最长回文的半径
    int pos[N][30];
    int init()//对原有的字符串进行扩充
    {
        int len = strlen(s),cnt=1;//s从0开始存
        sn[0] = '$';
        sn[1] = '#';
        for (int i = 0; i < len;i++)
        {
            sn[++cnt] = s[i];
            sn[++cnt] = '#';
        }
        sn[++cnt] = '';
        return cnt;//返回扩充后的字符串长度
    }
    ll manacher()
    {
        int len = init();//预处理扩充
        int id, mx = 0;
        for (int i = 1; i < len;i++)
        {
            sen[i] = mx > i ? min(sen[2 * id - i], mx - i) : 1;
            while(sn[i-sen[i]]==sn[i+sen[i]])
                sen[i]++;
            if(mx<i+sen[i])
            {
                id = i;
                mx = i + sen[i];
            }
        }
        ll res=0;
        for(int i=2;i<len-1;i++)
        {
            int p=i/2-1;//cout<<"i="<<i<<endl;
            int t=0;
            if((sen[i]-1)&1) t=sen[i]/2;
            else t=(sen[i]-1)/2;
            for(int j=0;j<26;j++)
            {
                int l=p-t;
                if(pos[p][j]>l) res+=(pos[p][j]-l);
            }
        }
        return res;
    }
    int main()
    {
        scanf("%s", s);
        int len=strlen(s);
        for(int i=0;i<26;i++)
            pos[0][i]=-1;
        pos[0][s[0]-'a']=0;
        for(int i=1;i<len;i++)
        {
            for(int j=0;j<26;j++)
                pos[i][j]=pos[i-1][j];
            pos[i][s[i]-'a']=i;
        }
        printf("%lld
    ",manacher());
        return 0;
    }
    
    
  • 相关阅读:
    Asp.Net AjaxCalendar控件使用
    My97 使用的一点技巧
    DOM结构展现工具—iedevtoolbar
    揭开正则表达式的神秘面纱
    在客户端遍历控件
    C#3.0学习(2)对象集合初始化器
    GridView中实现CheckBox的全选
    C#3.0学习(1)隐含类型局部变量和扩展方法
    利用HttpModule实现防sql注入
    SQL 计算一個字符串在另一个字符串中出現的次数
  • 原文地址:https://www.cnblogs.com/1024-xzx/p/13219081.html
Copyright © 2020-2023  润新知