zoukankan      html  css  js  c++  java
  • manacher算法_求最长回文子串长度

    很好的总结,转自:

    http://blog.csdn.net/dyx404514/article/details/42061017

    总结为:两大情况,三小情况。

    两大情况:I. i <= p  

    1.要处理的位置i及i为中心的回文半径Len[i] < p-i已经完全包含在某个回文中了,这种情况不用计算,len[i] = len[j]。

    2.要处理的位置i在某个回文中,但是以i为中心的回文半径len[i] >= p-i,需要往后匹配,重新更新p,及对应的po和Len[i];

    II. i > p

    要计算的位置已经超出某个回文了,之前的回文已经没用,要重新计算新的位置了。只能挨个匹配了。

     1 // manacher.cpp : 定义控制台应用程序的入口点。
     2 //
     3 
     4 #include "stdafx.h"
     5 #include <iostream>
     6 #include <string>
     7 #include <vector>
     8 #include <iterator>
     9 using namespace std;
    10 
    11 string ManaStr(string &orgStr,int length)
    12 {//构造“马拉车”串
    13     if(length == 0)
    14         return NULL;
    15 
    16     string manacherString(2*length+1,'#');
    17     for(int i = 0;i < length;i++)
    18         manacherString[2*i+1] = orgStr[i];
    19 
    20     cout<<manacherString<<endl;
    21     return manacherString;
    22 }
    23 
    24 int manacher(string &manStr,int manacherLen)
    25 {//“马拉车”计算过程,主要是每个位置对应的回文半径数组的生成,pArr[i]
    26     if(manacherLen == 0)
    27         return 0;
    28 
    29     int Len[25];//回文半径数组
    30     for(int i = 0; i <25;i++)
    31         Len[i] = 0;
    32     for(int i = 0; i <25;i++)
    33         cout<<Len[i];
    34     int po = 0;//某个回文中心
    35     int mostRight = -1;//某个回文串最右的位置,并不包含这个位置
    36     int result = 0;
    37 
    38     //for(int i = 0;i != manacherLen;i++)
    39     for(int i = 0;i != 25;i++)
    40     {
    41         Len[i] = mostRight > i ? min(mostRight-i,Len[2*po-i]):1;
    42         /*
    43           当前位置i包含在某个回文串中,那么Len[i]的值就是i到mostRight或者
    44           关于po对称的j位置的Len值(j = 2*po-i)
    45         */
    46         while(i+Len[i] < manacherLen && i-Len[i] >=0)
    47         {
    48             if(manStr[i - Len[i]] == manStr[i + Len[i]])
    49                 Len[i]++;//检查是否可扩
    50             else
    51                 break;
    52         }
    53         if(i+Len[i] > mostRight)
    54         {//扩到mostRight之外了,旧的回文串就不起作用了,更新成新的回文串
    55             //mostRight = Len[i] + 1;!!!!!!艹!!!会死人啊
    56             mostRight = Len[i] + i;
    57             po = i;
    58         }
    59         result = max(result,Len[i]);
    60     }
    61     return result - 1;
    62 }
    63 
    64 int _tmain(int argc, _TCHAR* argv[])
    65 {
    66     string originalString = "abc1234321ab";//结果应该为7
    67     int originalLen = originalString.length();
    68     //int originalLen = 12;
    69     cout<<originalString<<endl;
    70     string manacherString = ManaStr(originalString,originalLen);
    71     int manStrLen = 2*originalLen + 1;
    72     cout<<"原串中包含的最长回文长度为:"<<manacher(manacherString,manStrLen)<<endl;
    73     system("pause");
    74     return 0;
    75 }
    manacher

     一个变形题

     1 // manacher_.cpp : 定义控制台应用程序的入口点。
     2 //题目:给定一个串,求 在串的后边添加最小字符使得整体都是回文
     3 //解法:利用manacher算法,当mostRight == length的时候停止,并记录下Len[i]
     4 //      找到包含最后一个字符的回文串,之前的逆序就是要求的结果
     5 //例子:abcd123321,在后边加dcba就是回文,返回dcba。
     6 
     7 
     8 
     9 #include "stdafx.h"
    10 #include <iostream>
    11 #include <string>
    12 using namespace std;
    13 
    14 string manStr(string &orgStr,int orgLen)
    15 {
    16     if(orgLen == 0)
    17         return NULL;
    18 
    19     string manaString(2*orgLen+1,'#');
    20     //string的一种构造方法string(num,ele)
    21     for(int i = 0; i < orgLen; i++)
    22         manaString[2*i+1] = orgStr[i];
    23 
    24     cout<<manaString<<endl;
    25     return manaString;
    26 }
    27 
    28 void manacherCore(string& mancherStr,int manaLen)
    29 {
    30     if(manaLen == 0)
    31         return;
    32     
    33     int mostEnd = 0;
    34     int mostRight = -1;
    35     int po = 0;
    36     int Len[21];
    37     for(int i = 0; i< 21; i++)
    38         Len[i] = 0;//初始化Len
    39 
    40     for(int i = 0;i != manaLen; i++)
    41     {
    42         Len[i] = mostRight > i? min(mostRight - i,Len[2*po-i]):1;
    43         //while(i+Len[i] < manaLen && i- manaLen > -1)麻痹又写错
    44         while(i+Len[i] < manaLen && i- Len[i] > -1)
    45         {
    46             if(mancherStr[i + Len[i]] == mancherStr[i - Len[i]])
    47                 Len[i]++;
    48             else
    49                 break;
    50         }
    51         if(i + Len[i] > mostRight)
    52         {
    53             mostRight =i + Len[i];
    54             po = i;
    55         }
    56         if(mostRight == manaLen)
    57         {
    58             mostEnd = Len[i];
    59             break;
    60         }
    61     }
    62     //string result(10-(mostEnd-1),'0');//保存结果的string
    63     string result(10-mostEnd+1,'0');//这里应该是原串长度10
    64     int resLen = result.length();
    65 
    66     for (int i = 0; i < resLen; i++)
    67         result[resLen-i-1] = mancherStr[2*i+1];
    68     cout<<result<<endl;
    69     
    70 }
    71 
    72 int _tmain(int argc, _TCHAR* argv[])
    73 {
    74     string orginalStr = "abcd123321";
    75     cout<<orginalStr<<endl;
    76     int orgLen = orginalStr.length();
    77     string mancherStr = manStr(orginalStr,orgLen);
    78     int manaLen = mancherStr.length();
    79     manacherCore(mancherStr,manaLen);
    80     system("pause");
    81     return 0;
    82 }
    manacher变形
  • 相关阅读:
    telnet c# 执行命令
    C# Windows服务安装、卸载批处理代码
    数据库高人 邹健 博客链接
    HDOJ_1232 并查集 畅通工程
    poj3461 KMP 小结
    HDOJ_2094 寻找冠军 set的简单应用
    HDOJ_1272 小希的迷宫 并查
    HDOJ_2754 素数种类统计
    linux下的jsp
    mysql
  • 原文地址:https://www.cnblogs.com/lp3318/p/5676558.html
Copyright © 2011-2022 走看看