Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/powershell/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Algorithm 添加最少数量的字符以生成回文_Algorithm_Palindrome - Fatal编程技术网

Algorithm 添加最少数量的字符以生成回文

Algorithm 添加最少数量的字符以生成回文,algorithm,palindrome,Algorithm,Palindrome,问题是: 给定任何字符串,添加尽可能少的字符,使其在线性时间内成为回文 我只能想出一个O(N2)溶液 有人能帮我一个O(N)解决方案吗?我假设您不能替换或删除任何现有字符 一个好的开始是反转其中一个字符串,并在反转的字符串和另一个字符串之间找到最长的公共子字符串(LCS)。因为这听起来像是一个家庭作业或面试问题,剩下的就交给你了 #包括 #包括 使用std::cout; 使用std::endl; 使用std::cin; int main(){ std::字符串字,左(“”); cin>>单词;

问题是:

给定任何字符串,添加尽可能少的字符,使其在线性时间内成为回文

我只能想出一个O(N2)溶液


有人能帮我一个O(N)解决方案吗?

我假设您不能替换或删除任何现有字符

一个好的开始是反转其中一个字符串,并在反转的字符串和另一个字符串之间找到最长的公共子字符串(LCS)。因为这听起来像是一个家庭作业或面试问题,剩下的就交给你了

#包括
#包括
使用std::cout;
使用std::endl;
使用std::cin;
int main(){
std::字符串字,左(“”);
cin>>单词;
大小\u t开始、结束;
for(start=0,end=word.length()-1;start还原字符串
  • 使用modified查找最新的匹配项(最简单的修改是将原始字符串附加到还原的字符串,并忽略len(string)之后的匹配项)
  • 将还原字符串中不匹配的其余部分追加到原始字符串
  • 1和3显然是线性的,2是线性的,因为Knuth-Morris-Pratt是线性的。

    如果只允许附加 Scala解决方案:

    def isPalindrome(s: String) = s.view.reverse == s.view
    
    def makePalindrome(s: String) = 
      s + s.take((0 to s.length).find(i => isPalindrome(s.substring(i))).get).reverse
    
    如果你被允许在任何地方插入字符 每个回文都可以看作是一组嵌套的字母对

    a  n  n  a         b  o  b
    |  |  |  |         |  *  |
    |   --   |         |     |
    ---------           -----
    

    若回文长度n为偶数,则有n/2对,如果是奇数,则中间有n/2对和一个字母(称之为退化的对)。 让我们用一对字符串索引来表示它们-左索引从字符串的左端开始计数,右索引从字符串的右端开始计数,两端都以索引0开始

    现在,让我们从外部到内部写对。在我们的示例中:

    anna: (0, 0) (1, 1)
    bob: (0, 0) (1, 1)
    
    为了使任何字符串都成为回文,我们将从字符串的两端一次添加一个字符,并在每一步中最终添加一个字符以生成一对正确的相同字符

    例如: 假设输入字是“blob”

  • 对(0,0)是(b,b)好的,没什么可做的,这对很好。让我们增加计数器
  • 对(1,1)是(l,o)。不匹配。所以让我们从左边的位置1添加“o”。现在我们的单词变成了“bolob”
  • 对(2,2)。我们甚至不需要查看字符,因为我们指向字符串中的同一索引。完成
  • 等一下,但我们这里有一个问题:在第2点中,我们任意选择在左侧添加一个字符。但我们也可以在右侧添加一个字符“l”。这将产生“blolb”,也是一个有效的回文。这有关系吗?不幸的是,这有关系,因为前面步骤中的选择可能会影响我们需要修复的对数,从而影响我们在未来步骤中需要添加的字符数

    简单算法:搜索所有可能的。这将给我们一个O(2^n)算法。 更好的算法:使用动态规划方法并修剪搜索空间

    为了使事情更简单,现在我们将插入新字符与查找正确的嵌套对序列(从外到内)以及稍后修复它们的对齐方式分离。因此对于单词“blob”,我们有以下几种可能性,两者都以退化对结尾:

    (0, 0) (1, 2)
    (0, 0) (2, 1)
    
    我们找到的这类对越多,修复原始字符串所需添加的字符就越少。找到的每对完整对都会给我们两个可以重用的字符。每对退化对都会给我们一个可以重用的字符

    该算法的主循环将以这样的方式迭代计算成对序列,即在步骤1中找到长度为1的所有有效成对序列。下一步将计算长度为2的序列,长度为3的第三个序列等。当在某一步中我们发现不可能时,这意味着上一步包含具有高精度的解最大成对数

    在每一步之后,我们将删除帕累托次优序列。如果一个序列的最后一对被另一个序列的最后一对支配,那么它与相同长度的另一个序列相比是次优的。例如,序列(0,0)(1,3)比(0,0)(1,2)差。后者为我们提供了更多的空间来查找嵌套对,并且我们保证至少找到我们为前者找到的所有对。但是序列(0,0)(1,2)既不比(0,0)(2,1)差也不比(0,0)(2,1)好.我们必须注意的一个小细节是,以退化对结尾的序列总是比以完整对结尾的序列更糟糕

    在将所有这些结合起来之后:

    def makePalindrome(str: String): String = {
    
      /** Finds the pareto-minimum subset of a set of points (here pair of indices).
        * Could be done in linear time, without sorting, but O(n log n) is not that bad ;) */
      def paretoMin(points: Iterable[(Int, Int)]): List[(Int, Int)] = {
        val sorted = points.toSeq.sortBy(identity)
        (List.empty[(Int, Int)] /: sorted) { (result, e) =>
          if (result.isEmpty || e._2 <= result.head._2)
            e :: result
          else
            result
        }
      }
    
      /** Find all pairs directly nested within a given pair.
        * For performance reasons tries to not include suboptimal pairs (pairs nested in any of the pairs also in the result)
        * although it wouldn't break anything as prune takes care of this. */
      def pairs(left: Int, right: Int): Iterable[(Int, Int)] = {
        val builder = List.newBuilder[(Int, Int)]
        var rightMax = str.length
        for (i <- left until (str.length - right)) {
          rightMax = math.min(str.length - left, rightMax)
          val subPairs =
            for (j <- right until rightMax if str(i) == str(str.length - j - 1)) yield (i, j)
    
          subPairs.headOption match {
            case Some((a, b)) => rightMax = b; builder += ((a, b))
            case None =>
          }
        }
    
        builder.result()
      }
    
      /** Builds sequences of size n+1 from sequence of size n */
      def extend(path: List[(Int, Int)]): Iterable[List[(Int, Int)]] =
        for (p <- pairs(path.head._1 + 1, path.head._2 + 1)) yield p :: path
    
      /** Whether full or degenerated. Full-pairs save us 2 characters, degenerated save us only 1. */
      def isFullPair(pair: (Int, Int)) =
        pair._1 + pair._2 < str.length - 1
    
      /** Removes pareto-suboptimal sequences */
      def prune(sequences: List[List[(Int, Int)]]): List[List[(Int, Int)]] = {
        val allowedHeads = paretoMin(sequences.map(_.head)).toSet
        val containsFullPair = allowedHeads.exists(isFullPair)
        sequences.filter(s => allowedHeads.contains(s.head) && (isFullPair(s.head) || !containsFullPair))
      }
    
      /** Dynamic-Programming step */
      @tailrec
      def search(sequences: List[List[(Int, Int)]]): List[List[(Int, Int)]] = {
        val nextStage = prune(sequences.flatMap(extend))
        nextStage match {
          case List() => sequences
          case x => search(nextStage)
        }
      }
    
      /** Converts a sequence of nested pairs to a palindrome */
      def sequenceToString(sequence: List[(Int, Int)]): String = {
        val lStr = str
        val rStr = str.reverse
    
        val half =
          (for (List(start, end) <- sequence.reverse.sliding(2)) yield
            lStr.substring(start._1 + 1, end._1) + rStr.substring(start._2 + 1, end._2) + lStr(end._1)).mkString
    
        if (isFullPair(sequence.head))
          half + half.reverse
        else
          half + half.reverse.substring(1)
      }
    
      sequenceToString(search(List(List((-1, -1)))).head)
    }
    
    def makePalindrome(str:String):String={
    /**查找一组点(此处为一对索引)的帕累托最小子集。
    *可以在线性时间内完成,无需排序,但O(n logn)并没有那么糟糕;)*/
    def paretoMin(点:Iterable[(Int,Int)]):List[(Int,Int)]={
    val排序=点到相等排序(标识)
    (List.empty[(Int,Int)]/:排序){(result,e)=>
    如果(result.isEmpty | | e.| u2这里看到这个解
    这比O(N^2)
    问题被细分为许多其他子问题
    例如:
    原“托斯托尔”
    反向“rototsot”
    这里的第二个位置是“o”,因此通过从原始字符串切入到“t”和“OSOT”,将问题分为两个部分
    对于“t”:解决方案为1
    对于“OSOT”:解决方案是2,因为LCS是“tot”,需要添加的字符是“os”
    所以总数是2+1=3

    O(n)时间解。 算法: 需要找到给定字符串中包含最后一个字符的最长回文。然后将不属于回文的所有字符按相反顺序添加到字符串的后面

    重点: 在这个问题中,最长的回文
    def  shortPalin( S):
        k=0
        lis=len(S)
            for i in range(len(S)/2):
            if S[i]==S[lis-1-i]:
                k=k+1
            else :break
        S=S[k:lis-k]
        lis=len(S)
        prev=0
        w=len(S)
        tot=0
        for i in range(len(S)):
            if i>=w:
                break;
            elif S[i]==S[lis-1-i]:
                 tot=tot+lcs(S[prev:i])
                 prev=i
                 w=lis-1-i
        tot=tot+lcs(S[prev:i])
        return tot
    
    def  lcs( S):
        if (len(S)==1):
            return 1
        li=len(S)
        X=[0 for x in xrange(len(S)+1)]
        Y=[0 for l in xrange(len(S)+1)]
        for i in range(len(S)-1,-1,-1):
            for j in range(len(S)-1,-1,-1):
                if S[i]==S[li-1-j]:
                    X[j]=1+Y[j+1]
                else:
                    X[j]=max(Y[j],X[j+1])
            Y=X
        return li-X[0]
    print shortPalin("tostotor")
    
     static public void makePalindrome()
        {
            //string word = "aababaa";
            //string word = "abacbaa";
            //string word = "abcbd";
            //string word = "abacac";
            //string word = "aBxyxBxBxyxB";
            //string word = "Malayal";
            string word = "abccadac";
    
            int j = word.Length - 1;
            int mark = j;
            bool found = false;
    
            for (int i = 0; i < j; i++)
            {
                char cI = word[i];
                char cJ = word[j];
    
                if (cI == cJ)
                {
                    found = true;
                    j--;
                    if(mark > i)
                        mark = i;
                }
                else
                {
                    if (found)
                    {
                        found = false;
                        i--;
                    }
                    j = word.Length - 1;
                    mark = j;
                }
            }
    
            for (int i = mark-1; i >=0; i--)
                word += word[i];
    
            Console.Write(word);
    
        }
    }
    
    str = 'xcbc' # Any string that you want.
    arr1 = str.split('')
    arr2 = arr1.reverse
    count = 0
    
    while(str != str.reverse)
      count += 1
      arr1.insert(count-1, arr2[count-1])
      str = arr1.join('')
    end
    
    puts str
    puts str.length - arr2.count
    
    #include <iostream>
    using namespace std;
    
    int length( char str[])
    {  int l=0;
      for( int i=0; str[i]!='\0'; i++, l++);
    return l;
    }
    int palin(char str[],int len)
    {  static int cnt;
       int s=0;
       int e=len-1;
       while(s<e){
        if(str[s]!=str[e]) {
                cnt++;
             return palin(str+1,len-1);}
        else{
             s++;
             e--;
         }
      }
    return cnt;
    }
      int main() {
        char str[100];
        cin.getline(str,100);
        int len = length(str);
        cout<<palin(str,len);
      }
    
    public static void main(String[] args) {
    
        String givenStr = "abtb";
        String palindromeStr = covertToPalindrome(givenStr);
        System.out.println(palindromeStr);
    
    }
    
    private static String covertToPalindrome(String str) {
    
        char[] strArray = str.toCharArray();
    
        int low = 0;
        int high = strArray.length - 1;
        int subStrIndex = -1;
    
        while (low < high) {
            if (strArray[low] == strArray[high]) {
                high--;
            } else {
                high = strArray.length - 1;
                subStrIndex = low;
            }
            low++;
        }
    
        return str +  (new StringBuilder(str.substring(0, subStrIndex+1))).reverse().toString();
    
    }
    
    public static void main(String args[])
    {
      String s=input();
      System.out.println(min_operations(s));
    }
    
    static String min_operations(String str)
    {
    
      int i=0;
      int j=str.length()-1;
      String ans="";
    
      while(i<j)
      {
       if(str.charAt(i)!=str.charAt(j))
       {
        ans=ans+str.charAt(i);
       }
       if(str.charAt(i)==str.charAt(j))
       {
          j--;
       }
    
        i++;
    }
    
     StringBuffer sd=new StringBuffer(ans);
     sd.reverse();
     return (sd.toString());
    
    }