Recursion 字符串缩减-编程竞赛。需要的解决方案

Recursion 字符串缩减-编程竞赛。需要的解决方案,recursion,dynamic-programming,puzzle,Recursion,Dynamic Programming,Puzzle,我有一个问题,要求我们将字符串缩减如下 输入是一个只有a、B或C的字符串。输出长度必须为 简化字符串 该字符串可以通过以下规则缩减 如果任何两个不同的字母相邻,则这两个字母可以是 替换为第三个字母 例如ABA->CA->B。所以最后的答案是1(缩减字符串的长度) 例如ABCCCCCCC 这不会变成cccc,因为它可以通过 ABCCCCC->AACCCCC->ABCCCCC->AACCC->ABCCC->AACC->ABC->AA 此处长度为2(CCCC的长度) 你如何处理这个问题 非常感谢 为了

我有一个问题,要求我们将字符串缩减如下

输入是一个只有
a
B
C
的字符串。输出长度必须为 简化字符串

该字符串可以通过以下规则缩减

如果任何两个不同的字母相邻,则这两个字母可以是 替换为第三个字母

例如
ABA
->
CA
->
B
。所以最后的答案是1(缩减字符串的长度)

例如
ABCCCCCCC

这不会变成
cccc
,因为它可以通过

ABCCCCC
->
AACCCCC
->
ABCCCCC
->
AACCC
->
ABCCC
->
AACC
->
ABC
->
AA

此处长度为2(CCCC的长度)

你如何处理这个问题

非常感谢


为了让事情更清楚:问题表明它需要缩减字符串的最小长度。因此,在上面的第二个示例中,有两种可能的解决方案,一种是
cccc
,另一种是
AA
。因此,答案是2,因为
AA
的长度是2,它小于
cccc
=8。

我假设您正在寻找缩减后可能获得的最短字符串的长度

一个简单的解决办法是以贪婪的方式探索所有的可能性,并希望它不会以指数级的速度爆炸。我将在这里编写Python伪代码,因为这更容易理解(至少对我来说;):

从集合导入数据
def try_REDUCT(字符串):
queue=deque([string])
最小长度=长度(字符串)
排队时:
string=queue.popleft()
如果长度(字符串)<最小长度:
最小长度=长度(字符串)
对于X范围内的i(长度(字符串)-1):
子字符串=字符串[i:(i+2)]
如果子字符串==“AB”或子字符串==“BA”:
queue.append(字符串[:i]+“C”+字符串[(i+2):])
elif子字符串==“BC”或子字符串==“CB”:
queue.append(字符串[:i]+“A”+字符串[(i+2):])
elif子字符串==“AC”或子字符串==“CA”:
queue.append(字符串[:i]+“B”+字符串[(i+2):])
返回最小长度

我认为基本思想是明确的:您使用一个队列(
std::deque
),将字符串添加到其中,然后在所有可能的缩减空间中实现一个简单的广度优先搜索。在搜索过程中,从队列中获取第一个元素,获取其所有可能的子字符串,执行所有可能的缩减,并将缩减后的字符串推回到队列中。当队列变空时,将探索整个空间。

这个问题的措辞方式,只有三种不同的可能性:

  • 如果字符串只有一个唯一字符,则长度与字符串的长度相同
  • 2/3。如果字符串包含多个唯一字符,则长度始终为1或2(基于字符的布局)

    编辑: 作为概念证明的一种方式,这里有一些语法及其扩展: 我应该注意到,虽然在我看来,这似乎是长度将减少到1或2这一事实的合理证明,但我可以合理地确定,确定这些长度中的哪一个将产生结果并不像我最初认为的那么简单(您仍然需要递归所有选项才能找到它)

    其中()表示空字符串,s^表示前面[A,B,C,()]字符的任意组合

    扩展语法:

    S_1 :   AS^|others
    S_2 :   AAS^|ABS^|ACS^|others
    S_3 :   AAAS^|
            AABS^ => ACS^ => BS^|
            AACS^ => ABS^ => CS^|
            ABAS^ => ACS^ => BS^|
            ABBS^ => CBS^ => AS^|
            ABCS^ => CCS^ | AAS^|
            ACAS^ => ABS^ => CS^|
            ACBS^ => AAS^ | BBS^|
            ACCS^ => BCS^ => AS^|
    
    同样的事情也会发生在以B和C(其他)开头的扩展语法中。有趣的情况是,我们有ACB和ABC(顺序中有三个不同的字符),这些情况导致语法似乎会导致更长的长度,但是:

    CCS^:   CCAS^|CCBS^|CCCS^|
            CBS^ => AS^|
            CAS^ => BS^|
            CCCS^|
    AAS^:   AAAS^|AABS^|AACS^|
            ACS^ => BS^|
            ABS^ => CS^|
            AAAS^|
    BBS^:   BBAS^|BBBS^|BBCS^|
            BCS^ => AS^|
            BAS^ => CS^|
            BBBS^|
    
    递归地,当剩余字符串仅包含其值时,它们只会导致更长的长度。然而,我们必须记住,这种情况也可以简化,因为如果我们以CCCS^的方式进入这一领域,那么我们之前曾有过ABC(或CBA)。如果我们回顾过去,我们本可以做出更好的决定:

    ABCCS^  =>  AACS^   =>  ABS^    =>  CS^ 
    CBACS^  =>  CBBS^   =>  ABS^    =>  CS^
    

    因此,在最好的情况下,在字符串末尾,当我们做出所有正确的决定时,我们会以剩余的1个字符的字符串结尾,后面再加1个字符(因为我们在末尾)。此时,如果字符相同,则长度为2,如果不同,则可以最后减少一次,最终长度为1。

    让我们使用以下规则定义一个自动机(K>=0):

    传入:A B C
    当前:--------------------------
    A、B、C
    A(2K+1)A(2K+2)AB AC
    A(2K+2)A(2K+3)AAB AAC
    AB CA CB ABC
    公元前
    美国广播公司
    
    并通过ABC的置换得到所有规则,从而得到完整的定义

    使用单个字母的所有输入字符串都是不可约的。如果输入字符串至少包含两个不同的字母,则最终状态(如AB或AAB)可以减少为一个字母,而最终状态(如ABC)可以减少为两个字母


    在ABC的例子中,我们仍然需要证明输入字符串不能通过另一个缩减序列缩减为单个字母。

    一个好的开始不是数一数你拥有最多的字母并寻找删除它的方法吗?继续这样做,直到我们只有一封信。我们可能有很多次,但只要它是相同的,我们不在乎,我们完成了

    避免像ABCCCCC这样的东西变成CCCC

    我们删除了最流行的字母:

    -ABCCCCCCC
    -AACCCC
    -ABCCCCC
    -AACCCC
    -ABCCC
    -AACC
    -ABC
    -AA

    我不同意上一张海报上说我们
    CCS^:   CCAS^|CCBS^|CCCS^|
            CBS^ => AS^|
            CAS^ => BS^|
            CCCS^|
    AAS^:   AAAS^|AABS^|AACS^|
            ACS^ => BS^|
            ABS^ => CS^|
            AAAS^|
    BBS^:   BBAS^|BBBS^|BBCS^|
            BCS^ => AS^|
            BAS^ => CS^|
            BBBS^|
    
    ABCCS^  =>  AACS^   =>  ABS^    =>  CS^ 
    CBACS^  =>  CBBS^   =>  ABS^    =>  CS^
    
       Incoming:    A       B       C
    Current:    --------------------------
    <empty>         A       B       C
    A(2K+1)         A(2K+2) AB      AC
    A(2K+2)         A(2K+3) AAB     AAC
    AB              CA      CB      ABC
    AAB             BA      ACB     BC
    ABC             CCA     AAB     AAC
    
    if((a == 0 && b == 0 && c == 0) ||
       (a == 0 && b == 0 && c != 0) ||
       (a == 0 && b != 0 && c == 0) ||
       (a != 0 && b == 0 && c == 0))
    {
        result = a+b+c;
    }
    else if(a != 0 && b != 0 && c != 0)
    {
        if((a%2 == 0 && b%2 == 0 && c%2 == 0) ||
           (a%2 == 1 && b%2 == 1 && c%2 == 1))
            result = 2;
        else
            result = 1;
    }
    else if((a == 0 && b != 0 && c != 0) || 
            (a != 0 && b == 0 && c != 0) || 
            (a != 0 && b != 0 && c == 0))
    {
        if(a%2 == 0 && b%2 == 0 && c%2 == 0)
            result = 2;
        else
            result = 1;
    }
    
        import java.util.LinkedList;
    import java.util.List;
    import java.util.Scanner;
    
    
    public class Sample {
    
        private static char[] res = {'a', 'b', 'c'};
        private char replacementChar(char a, char b) {
            for(char c : res) {
                if(c != a && c != b) {
                    return c;
                }
            }
            throw new IllegalStateException("cannot happen. you must've mucked up the resource");
        }
    
        public int processWord(String wordString) {
            if(wordString.length() < 2) {
                return wordString.length();
            }
            String wordStringES = reduceFromEnd(reduceFromStart(wordString));
            if(wordStringES.length() == 1) {
                return 1;
            }
            String wordStringSE = reduceFromStart(reduceFromEnd(wordString));
            if(wordString.length() == 1) {
                return 1;
            }
    
            int aLen;
            if(isReduced(wordStringSE)) {
                aLen = wordStringSE.length();
            } else {
                aLen = processWord(wordStringSE);
            }
            int bLen;
            if(isReduced(wordStringES)) {
                bLen = wordStringES.length();
            } else {
                bLen = processWord(wordStringES);
            }
            return Math.min(aLen, bLen);
        }
    
        private boolean isReduced(String wordString) {
            int length = wordString.length();
            if(length < 2) {
                return true;
            }
            for(int i = 1; i < length; ++i) {
                if(wordString.charAt(i) != wordString.charAt(i - 1)) {
                    return false;
                }
            }
            return wordString.charAt(0) == wordString.charAt(length - 1);
        }
    
        private String reduceFromStart(String theWord) {
            if(theWord.length() < 2) {
                return theWord;
            }
    
            StringBuilder buffer = new StringBuilder();
            char[] word = theWord.toCharArray();
            char curChar = word[0];
    
            for(int i = 1; i < word.length; ++i) {
                if(word[i] != curChar) {
                    curChar = replacementChar(curChar, word[i]);
                    if(i + 1 == word.length) {
                        buffer.append(curChar);
                        break;
                    }
                } else {
                    buffer.append(curChar);
                    if(i + 1 == word.length) {
                        buffer.append(curChar);
                    }
                }
            }
            return buffer.toString();
        }
    
        private String reduceFromEnd(String theString) {
            if(theString.length() < 2) {
                return theString;
            }
    
            StringBuilder buffer = new StringBuilder(theString);
            int length = buffer.length();
            while(length > 1) {
                char a = buffer.charAt(0);
                char b = buffer.charAt(length - 1);
                if(a != b) {
                    buffer.deleteCharAt(length - 1);
                    buffer.deleteCharAt(0);
                    buffer.append(replacementChar(a, b));
                    length -= 1;
                } else {
                    break;
                }
            }
            return buffer.toString();
        }
    
        public void go() {
            Scanner scanner = new Scanner(System.in);
            int numEntries = Integer.parseInt(scanner.nextLine());
            List<Integer> counts = new LinkedList<Integer>(); 
            for(int i = 0; i < numEntries; ++i) {
                counts.add((processWord(scanner.nextLine())));
            }
            for(Integer count : counts) {
                System.out.println(count);
            }
        }
    
        public static void main(String[] args) {
            Sample solution = new Sample();
            solution.go();
        }
    }
    
    int same(char* s){
        int i=0;
        for(i=0;i<strlen(s)-1;i++){
                if(*(s+i) == *(s+i+1))
                        continue;
                else
                        return 0;
        }
        return 1;
    }
    
    
    int reduceb(char* s){
        int ret = 0,a_sum=0,i=0;
        int len = strlen(s);
        while(1){
                i=len-1;
                while(i>0){
                        if ((*(s+i)) == (*(s+i-1))){
                                        i--;
                                        continue;
                        } else {
                                a_sum = (*(s+i)) + (*(s+i-1));
                                *(s+i-1) = SUM - a_sum;
                                *(s+i) = '\0';
                                len--;
                        }
                        i--;
                }
                if(same(s) == 1){
                        return strlen(s);
                        }
    }
    }
    
    
    int reducef(char* s){
        int ret = 0,a_sum=0,i=0;
        int len = strlen(s);
        while(1){
                i=0;
                while(i<len-1){
                        if ((*(s+i)) == (*(s+i+1))){
                                        i++;               
                                        continue;
                        } else {
                                a_sum = (*(s+i)) + (*(s+i+1));
                                *(s+i) = SUM - a_sum;
                                int j=i+1;
                                for(j=i+1;j<len;j++)
                                        *(s+j) = *(s+j+1);
                                len--;
                        }
                        i++;
                }
                if(same(s) == 1){
                        return strlen(s);
                        }
    }
    }
    
    int main(){
        int n,i=0,f=0,b=0;
        scanf("%d",&n);
        int a[n];
    
        while(i<n){
                char* str = (char*)malloc(101);
                scanf("%s",str);
                char* strd = strdup(str);
                f = reducef(str);
                b = reduceb(strd);
    
                if( f > b)
                        a[i] = b;
                else
                        a[i] = f;
                free(str);
                free(strd);
                i++;
        }
    
        for(i=0;i<n;i++)
                printf("%d\n",a[i]);
    
    int same(char* s){
        int i=0;
        for(i=0;i<strlen(s)-1;i++){
                if(*(s+i) == *(s+i+1))
                        continue;
                else
                        return 0;
        }
        return 1;
    }
    
    
    int reduceb(char* s){
        int ret = 0,a_sum=0,i=0;
        int len = strlen(s);
        while(1){
                i=len-1;
                while(i>0){
                        if ((*(s+i)) == (*(s+i-1))){
                                        i--;
                                        continue;
                        } else {
                                a_sum = (*(s+i)) + (*(s+i-1));
                                *(s+i-1) = SUM - a_sum;
                                *(s+i) = '\0';
                                len--;
                        }
                        i--;
                }
                if(same(s) == 1){
                        return strlen(s);
                        }
    }
    }
    
    
    int reducef(char* s){
        int ret = 0,a_sum=0,i=0;
        int len = strlen(s);
        while(1){
                i=0;
                while(i<len-1){
                        if ((*(s+i)) == (*(s+i+1))){
                                        i++;               
                                        continue;
                        } else {
                                a_sum = (*(s+i)) + (*(s+i+1));
                                *(s+i) = SUM - a_sum;
                                int j=i+1;
                                for(j=i+1;j<len;j++)
                                        *(s+j) = *(s+j+1);
                                len--;
                        }
                        i++;
                }
                if(same(s) == 1){
                        return strlen(s);
                        }
    }
    }
    
    int main(){
        int n,i=0,f=0,b=0;
        scanf("%d",&n);
        int a[n];
    
        while(i<n){
                char* str = (char*)malloc(101);
                scanf("%s",str);
                char* strd = strdup(str);
                f = reducef(str);
                b = reduceb(strd);
    
                if( f > b)
                        a[i] = b;
                else
                        a[i] = f;
                free(str);
                free(strd);
                i++;
        }
    
        for(i=0;i<n;i++)
                printf("%d\n",a[i]);
    
    import java.io.*;
    import java.util.*;
    
    class StringSim{
    
        public static void main(String args[]){
            Scanner sc = new Scanner(System.in);
            StringTokenizer st = new StringTokenizer(sc.nextLine(), " ");
            int N = Integer.parseInt(st.nextToken());
            String op = "";
            for(int i=0;i<N;i++){
                String str = sc.nextLine();
                op = op + Count(str) + "\n";
            }
            System.out.println(op);
        }
    
        public static int Count( String str){
            int min = Integer.MAX_VALUE;
            char pre = str.charAt(0);
            boolean allSame = true;
            //System.out.println("str :" + str);
            if(str.length() == 1){
                return 1;
            }
            int count = 1;
            for(int i=1;i<str.length();i++){
                //System.out.println("pre: -"+ pre +"- char at "+i+" is : -"+ str.charAt(i)+"-");
                if(pre != str.charAt(i)){
                    allSame = false;
                    char rep = (char)(('a'+'b'+'c')-(pre+str.charAt(i)));
                    //System.out.println("rep :" + rep);
                    if(str.length() == 2)
                        count = 1;
                    else if(i==1)
                        count = Count(rep+str.substring(2,str.length()));
                    else if(i == str.length()-1) 
                        count = Count(str.substring(0,str.length()-2)+rep);
                    else
                        count = Count(str.substring(0,i-1)+rep+str.substring(i+1,str.length()));
    
                    if(min>count) min=count;
                }else if(allSame){
                    count++;
                    //System.out.println("count: " + count);
                }
                pre = str.charAt(i);
            }
            //System.out.println("min: " + min);
            if(allSame) return count;
            return min;
        }
    
    }
    
    import java.io.*;
    import java.util.*;
    
    class StringSim{
    
    public static void main(String args[]){
        Scanner sc = new Scanner(System.in);
        StringTokenizer st = new StringTokenizer(sc.nextLine(), " ");
        int N = Integer.parseInt(st.nextToken());
        String op = "";
        for(int i=0;i<N;i++){
            String str = sc.nextLine();
            op = op + Count(str) + "\n";
        }
        System.out.println(op);
    }
    
    public static int Count( String str){
        int min = Integer.MAX_VALUE;
        char pre = str.charAt(0);
        boolean allSame = true;
        //System.out.println("str :" + str);
        if(str.length() == 1){
            return 1;
        }
        int count = 1;
        for(int i=1;i<str.length();i++){
            //System.out.println("pre: -"+ pre +"- char at "+i+" is : -"+ str.charAt(i)+"-");
            if(pre != str.charAt(i)){
                allSame = false;
                char rep = (char)(('a'+'b'+'c')-(pre+str.charAt(i)));
                //System.out.println("rep :" + rep);
                if(str.length() == 2)
                    count = 1;
                else if(i==1)
                    count = Count(rep+str.substring(2,str.length()));
                else if(i == str.length()-1) 
                    count = Count(str.substring(0,str.length()-2)+rep);
                else
                    count = Count(str.substring(0,i-1)+rep+str.substring(i+1,str.length()));
    
                if(min>count) min=count;
            }else if(allSame){
                count++;
                //System.out.println("count: " + count);
            }
            pre = str.charAt(i);
        }
        //System.out.println("min: " + min);
        if(allSame) return count;
        return min;
      }
    }
    
    len = strlen (str) ;
    index = 0 ;
    flag = 0 ;
    
    /* 1st pass */
    for ( i = len-1 ; i > 0 ; i -- ) {
      if ( str[i] != str[i-1] ) {
        str[i-1] = getChar (str[i], str[i-1]) ;
        if (i == 1) {
          output1[index++] = str[i-1] ;
          flag = 1 ;
          break ;
        }
      }
      else output1[index++] = str[i] ;
    
    }
    
    if ( flag == 0 ) 
      output1[index++] = str[i] ;
    output1[index] = '\0';
    
    def reduce(string):
        a = string.count('a')
        b = string.count('b')
        c = string.count('c')
        if ([a,b,c].count(0) >= 2):
            return a+b+c
        elif (all(v % 2 == 0 for v in [a,b,c]) or all(v % 2 == 1 for v in [a,b,c])):
            return 2
        else:
            return 1
    
            int previous = a.charAt(0);
            boolean same = true;
            int c = 0;
            for(int i = 0; i < a.length();++i){
                c ^= a.charAt(i)-'a'+1;
                if(a.charAt(i) != previous) same = false;
            } 
            if(same) return a.length();
            if(c==0) return 2;
            else return 1;
    
     |1 A B C
    -+------- 
    1|1 A B C
    A|A 1 C B
    B|B C 1 A
    C|C B A 1
    
    //C# Coding
    
    using System;
    
    using System.Collections.Generic;
    
    
    namespace ConsoleApplication1
    {
    
    class Program
        {
    
    static void Main(string[] args)
    
    {
    
    /*
             Keep all the rules in Dictionary object 'rules'; 
             key - find string, value - replace with value 
             eg: find "AB" , replace with "AA" 
            */
    
            Dictionary<string, string> rules = new Dictionary<string, string>();
            rules.Add("AB", "AA");
            rules.Add("BA", "AA");
            rules.Add("CB", "CC");
            rules.Add("BC", "CC");
            rules.Add("AA", "A");
            rules.Add("CC", "C");
    
            // example string
            string str = "AABBCCCA";
    
            //output
            Console.WriteLine(fnRecurence(rules, str));
            Console.Read();
        }
    
        //funcation for applying all the rules to the input string value recursivily
        static string fnRecurence(Dictionary<string, string> rules,string str)
        {
            foreach (var rule in rules)
            {
                if (str.LastIndexOf(rule.Key) >= 0)
                {
                    str = str.Replace(rule.Key, rule.Value);
                }
            }
    
            if(str.Length >1)
            {
                int find = 0;
                foreach (var rule in rules)
                {
                    if (str.LastIndexOf(rule.Key) >= 0)
                    {
                        find = 1;
                    }
                }
    
                if(find == 1)
                {
                    str = fnRecurence(rules, str);
                }
                else
                {
                    //if not find any exit 
                    find = 0;
                    str = str;
                    return str;
                }
            }
    
            return str;
    
        }
    
    
    }
    
    import java.util.Scanner;
    
    public class StringReduction {
    
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        String str = sc.nextLine();
        int length = str.length(); 
        String result = stringReduction(str);
        System.out.println(result); 
    }
    
    private static String stringReduction(String str) {
        String result = str.substring(0);
        if(str.length()<2){
            return str;
        }
        if(str.length() == 2){
            return combine(str.charAt(0),str.charAt(1));
        }
        for(int i =1;i<str.length();i++){
            if(str.charAt(i-1) != str.charAt(i)){ 
                String temp = str.substring(0, i-1) + combine(str.charAt(i-1),str.charAt(i)) + str.substring(i+1, str.length()); 
                String sub = stringReduction(temp);
                if(sub.length() < result.length()){
                    result = sub;
                }
            }
        }
        return result;
    }
    
    private static String combine(char c1, char c2) { 
        if(c1 == c2){
            return "" + c1 + c2;
        }
        else{
            if(c1 == 'a'){
                if(c2 == 'b'){
                    return "" + 'c';
                }
                if(c2 == 'c') {
                    return "" + 'b';
                }
            }
            if(c1 == 'b'){
                if(c2 == 'a'){
                    return "" + 'c';
                }
                if(c2 == 'c') {
                    return "" + 'a';
                }
            }
            if(c1 == 'c'){
                if(c2 == 'a'){
                    return "" + 'b';
                }
                if(c2 == 'b') {
                    return "" + 'a';
                }
            }
            return null;
        } 
    }
    
    public static int StringReduction(string str)
        {
            if (str.Length == 1)
                return 1;
            else
            {
                int prevAns = str.Length;
                int newAns = 0;
    
                while (prevAns != newAns)
                {
                    prevAns = newAns;
                    string ansStr = string.Empty;
                    int i = 1;
                    int j = 0;
                    while (i < str.Length)
                    {
                        if (str[i] != str[j])
                        {
                            if (str[i] != 'a' && str[j] != 'a')
                            {
                                ansStr += 'a';
                            }
                            else if (str[i] != 'b' && str[j] != 'b')
                            {
                                ansStr += 'b';
                            }
                            else if (str[i] != 'c' && str[j] != 'c')
                            {
                                ansStr += 'c';
                            }
    
                            i += 2;
                            j += 2;
                        }
                        else
                        {
                            ansStr += str[j];
                            i++;
                            j++;
                        }
                    }
    
                    if (j < str.Length)
                    {
                        ansStr += str[j];
                    }
    
                    str = ansStr;
                    newAns = ansStr.Length;
                }
    
                return newAns;
            }
        }