• HDU 3068 &&HDU 3294 +最长回文串—— manacher


    HDU 3068 http://acm.hdu.edu.cn/showproblem.php?pid=3068

    HDU 3294http://acm.hdu.edu.cn/showproblem.php?pid=3294

    感觉DP相对实现起来更简洁一些,很容易想到,可以用bool dp[i][j]:表示从i到j是否为回文串,然后最长长度用一个变量记录就好

    如果dp[i][j]为回文串,那么dp[i+1][j-1]必为回文串且s[i]==s[j],所以可以得到递推关系 

    if(dp[i+1]][j-1]&&s[i]==s[j])  dp[i][j]=1;  maxlen=max(maxlen,i-j+1);

    但是上述判断条件并不对……上面的条件漏掉了一个单个字符必为回文串的情况,第二个判断条件再加一个||j-i<2即可,或者最开始初始化dp数组的时候把i==j的部分赋值为true;

    模板模板↓↓↓

    bool  dp[n][n];
    string s;
    int n;
    int DP() 
    { memset(dp, 0, sizeof(dp)); int maxlen = 0; for (int j = 0; j < s.length(); j++) for (int i = j; i >= 0; i--) if(s[i]==s[j]&&(j-i<2|| dp[i + 1][j - 1])) { dp[i][j] = 1; maxlen = max(maxlen, j - i + 1); } return maxlen; }

    但是……dp数组这样开就太大了……相对短一些的字符串还能用,长的就不行了……

    manacher

    不会manacher的话,可以参考这个:https://segmentfault.com/a/1190000003914228#articleHeader8

    HDU 3086

    #include<iostream>
    #include<stdio.h>
    #include<string.h>
    #include<algorithm>
    using namespace std;
    const int MAX = 110000 + 10;
    char s[MAX*2];//数组要开两倍的
    int rl[MAX*2];
    int n,pos,maxlen,maxright;
    int manacher()
    {
        for (int i = n; i >= 0; i--)
        {
            s[2 * i + 2] = s[i];
            s[2 * i + 1] = '#';
        }
        s[0] = '*';
        s[n * 2 + 2] = '';
        //大佬的小技巧,防止数组越界
        for (int i = 2; i < 2 * n + 1; i++)
        {
            if (maxright > i)  //i在pos左边
                rl[i] = min(rl[2 * pos-i], maxright- i);//i在pos右边
            else rl[i] = 1;
            while (s[i - rl[i]] == s[i + rl [i]]) rl[i]++; //向两边扩展
            if (maxright < rl[i]+i - 1)  //更新maxright
            {
                maxright = rl[i] + i - 1; pos = i;
            }
            if (maxlen < rl[i]) maxlen = rl[i];
        }
        return maxlen-1;
    }
    int main()
    {
        while (scanf("%s", s)!=EOF)
        {
            n = strlen(s); maxright = 0;
            pos = 0; maxlen = 0;
            printf("%d
    ",manacher());
        }
        return 0;
    }

    HDU3298  //跟上边一毛一样,不过需要在记录最大长度的时候顺便记录起始终止位置 start=(i-maxlen)/2  ; end=(i+maxlen)/2-2

    #include<iostream>
    #include<stdio.h>
    #include<string.h>
    #include<algorithm>
    using namespace std;
    const int MAX = 200000 + 10;
    int rl[MAX * 2];
    char s[MAX * 2],t[MAX*2], a[5];
    int len, maxlen, pos, st,maxright,ed;
    void manacher()
    {
        s[0] = '*'; s[2 * len + 2] = '';
        for (int i = 0; i < len; i++)
        {
            s[i * 2 + 1] = '#';
            s[i * 2 + 2] = t[i];
        }
        for (int i = 2; i < 2 * len + 2; i++)
        {
            if (i < maxright) rl[i] = min(maxright - i, rl[2 * pos - i]);
            else rl[i] = 1;
            while (s[i + rl[i]] == s[i - rl[i]]) rl[i]++;
            if (i + rl[i]-1 > maxright)
            {
                maxright = i + rl[i]-1;
                pos = i;
            }
            if (maxlen < rl[i])
            {
                maxlen = rl[i];
                st =(i-rl[i])/2;
                ed = (i + rl[i]) / 2-2;
            }
        }
        maxlen--;
    }
    
    int main()
    {
        while (scanf("%s%s",a,t)!= EOF)
        {
            //getchar();
            len = strlen(t);
            for (int i = 0; i < len; i++)
            {
                int b = t[i] - a[0];
                if (b < 0) b += 26;
                t[i] = b + 'a';
            }
            maxlen = 0;
            maxright = 0; pos = 0;
            st = 0; ed = 0;
            manacher();
            if (maxlen==1)printf("No solution!"); 
            else 
            {
                printf("%d %d
    ", st, ed);
                for (int i = st; i <= ed; i++)
                    printf("%c",t[i] );
            }    
            puts("");
        }
      return 0;
    }
  • 相关阅读:
    JS框架_(Bootstrap.js)实现简单的轮播图
    Unity3D_(网格导航)简单物体自动寻路
    Android_(菜单)选项菜单
    Android_(传感器)获取手机中的传感器
    Java基础__Java中常用数学类Math那些事
    Java基础__Java中异常处理那些事
    Android_(控件)动态添加或删除Spinner下拉菜单
    Android_(消息提示)多种使用Toast的消息提示
    Java基础__随机生成1~15之间不重复的数字
    Android_(自动化)获取手机存储卡的容量
  • 原文地址:https://www.cnblogs.com/Egoist-/p/7423455.html
Copyright © 2020-2023  润新知