在c++中找到左、右和相等的最长子串

To find the longest substring with equal sum in left and right in C++

本文关键字:子串 c++      更新时间:2023-10-16

我正在解决一个问题,与我有一些问题:

完成函数getEqualSumSubstring,该函数接受一个参数。单个参数是一个字符串s,它只包含非零数字。此函数应打印s的最长连续子串的长度,使子串的长度为2*N位,并且最左边的N位数字之和等于最右边的N位数字之和。如果没有这样的字符串,你的函数应该打印0。

int getEqualSumSubstring(string s) {
int i=0,j=i,foundLength=0;
    for(i=0;i<s.length();i++)
    {
        for(j=i;j<s.length();j++)
        {
            int temp = j-i;
            if(temp%2==0)
            {
                int leftSum=0,rightSum=0;
                string tempString=s.substr(i,temp);
                for(int k=0;k<temp/2;k++)
                {
                    leftSum=leftSum+tempString[k]-'0';
                    rightSum=rightSum+tempString[k+(temp/2)]-'0';
                }
                if((leftSum==rightSum)&&(leftSum!=0))
                    if(s.length()>foundLength)
                    foundLength=s.length(); 
            }
        }
    }
    return(foundLength);
}

问题是这段代码对一些样本有效,而对其他样本无效。因为这是一个考试类型的问题,所以我也没有测试用例。

代码正常运行

int getEqualSumSubstring(string s) {
    int i=0,j=i,foundLength=0;
    for(i=0;i<s.length();i++)
    {
        for(j=i;j<s.length();j++)
        {
            int temp = j-i+1;
            if(temp%2==0)
            {
                int leftSum=0,rightSum=0;
                string tempString=s.substr(i,temp);
                // printf("%d ",tempString.length());
                for(int k=0;k<temp/2;k++)
                {
                    leftSum=leftSum+tempString[k]-48;
                    rightSum=rightSum+tempString[k+(temp/2)]-48;
                }
                if((leftSum==rightSum)&&(leftSum!=0))
                    if(tempString.length()>foundLength)
                    foundLength=tempString.length(); 
            }
        }
    }
    return(foundLength);
}

temp变量必须为j-i+1。否则,整个字符串是答案的情况将不会被涵盖。此外,我们需要做斯科特建议的更改。

这是我的解决方案,我可以确认工作。上面的那些并没有真正为我工作-它们不知何故给了我编译错误。我在InterviewStreet上得到了同样的问题,想出了一个糟糕的,不完整的解决方案,对9/15的测试用例有效,所以我不得不花更多的时间编码。

的想法是,而不是关心得到左和右和(这是我最初所做的),我将得到所有可能的子字符串的每一半(左和右一半)的给定输入,排序和附加到两个单独的列表,然后看看是否有任何匹配。

为什么?

假设字符串"423"answers"234"有相同的和;如果我对它们进行排序,它们都是"234",因此是匹配的。由于这些数字必须连续且长度相等,因此我不再需要担心必须将它们加起来作为数字并进行检查。

例如,如果输入的是12345678,那么在左边,for循环将返回:

[1, 12123, 1234, 23234, 3, 34)

右边:

[5, 56567, 5678,…]

等等

但是,我只考虑长度至少为2的子字符串。

我将每个子字符串附加到数组列表中,先转换为字符数组,然后再转换回字符串。

那么现在所有这些都完成了,下一步是检查这两个数组列表中是否有相同数字的相同字符串。我只是对照temp_a的第一个字符串检查temp_b的每个字符串,然后对照temp_a的第二个字符串,以此类推。

如果我得到一个匹配(比如,"234"answers"234"),我将这些匹配子字符串的长度设置为我的tempCount (tempCount = 3)。我还有另一个名为'count'的变量来跟踪这些匹配子字符串的最大长度(如果这是第一次出现匹配,那么count = 0被tempCount = 3覆盖,所以count = 3)。

对于带有变量int end的奇/偶字符串长度,这样做的原因是在代码s.length()/2+j行中,输入的长度恰好是11,那么:

s.length() = 11

s.length()/2 = 11/5 = 5.5 = 5

那么在for循环中,s.length()/2 + j,其中j的最大值是s.length()/2,将变成:

5 + 5 = 10

它没有达到我需要达到的s.length()来获得字符串的最后一个索引。

这是因为子字符串函数要求的结束索引值比charAt(i)之类的值大1。

为了演示,输入"47582139875"将生成以下输出:[47, 457, 4578, 24578, 57, 578, 2578, 58, 258, 28] <——左半部分的子字符串[139, 1389, 13789, 135789, 389, 3789, 35789, 789, 5789, 578] <——右半边的子字符串578 <——最长的匹配6 <——'578'的长度x 2

public static int getEqualSumSubtring(String s){
    // run through all possible length combinations of the number string on left and right half
    // append sorted versions of these into new ArrayList
    ArrayList<String> temp_a = new ArrayList<String>();
    ArrayList<String> temp_b = new ArrayList<String>();
    int end; // s.length()/2 is an integer that rounds down if length is odd, account for this later 
    for( int i=0; i<=s.length()/2; i++ ){
        for( int j=i; j<=s.length()/2; j++ ){
            // only account for substrings with a length of 2 or greater
            if( j-i > 1 ){ 
                char[] tempArr1 = s.substring(i,j).toCharArray();
                Arrays.sort(tempArr1);
                String sorted1 = new String(tempArr1);
                temp_a.add(sorted1);
                //System.out.println(sorted1);
                if( s.length() % 2 == 0 )
                    end = s.length()/2+j;
                else // odd length so we need the extra +1 at the end
                    end = s.length()/2+j+1; 
                char[] tempArr2 = s.substring(i+s.length()/2, end).toCharArray();
                Arrays.sort(tempArr2);
                String sorted2 = new String(tempArr2);
                temp_b.add(sorted2);
                //System.out.println(sorted2);
            }
        }
    }
    // For reference
    System.out.println(temp_a);
    System.out.println(temp_b);
    // If the substrings match, it means they have the same sum
    // Keep track of longest substring
    int tempCount = 0 ;
    int count = 0;
    String longestSubstring = "";
    for( int i=0; i<temp_a.size(); i++){
        for( int j=0; j<temp_b.size(); j++ ){
            if( temp_a.get(i).equals(temp_b.get(j)) ){
                tempCount = temp_a.get(i).length();
                if( tempCount > count ){
                    count = tempCount;
                    longestSubstring = temp_a.get(i);
                }
            }
        }
    }
    System.out.println(longestSubstring);
    return count*2;
}

这是我对这个问题的解决方案,包括测试。我添加了一个额外的函数,只是因为我觉得它使解决方案比上面的解决方案更容易阅读。

#include <string>
#include <iostream>
using namespace std;
int getMaxLenSumSubstring( string s ) 
{
    int N = 0; // The optimal so far...
int leftSum = 0, rightSum=0, strLen=s.size();
int left, right;
for(int i=0;i<strLen/2+1;i++) {
    left=(s[i]-int('0')); right=(s[strLen-i-1]-int('0'));
    leftSum+=left; rightSum+=right;
    if(leftSum==rightSum) N=i+1;
}
return N*2;
}
int getEqualSumSubstring( string s ) {
    int maxLen = 0, substrLen, j=1;
for( int i=0;i<s.length();i++ ) {
    for( int j=1; j<s.length()-i; j++ ) {
        //cout<<"Substring = "<<s.substr(i,j);
        substrLen = getMaxLenSumSubstring(s.substr(i,j));
        //cout<<", Len ="<<substrLen;
        if(substrLen>maxLen) maxLen=substrLen;
    }
}
return maxLen;
}

这是我做的一些测试。基于以上的例子,他们似乎是对的。

int main() {
    cout<<endl<<"Test 1 :"<<getEqualSumSubstring(string("123231"))<<endl;
    cout<<endl<<"Test 2 :"<<getEqualSumSubstring(string("986561517416921217551395112859219257312"))<<endl;
    cout<<endl<<"Test 3:"<<getEqualSumSubstring(string("47582139875"))<<endl;
}

下面的代码不应该使用tempString.length()而不是s.l ong ()

if((leftSum==rightSum)&&(leftSum!=0))
    if(s.length()>foundLength)
        foundLength=s.length(); 
 Below is my code for the question... Thanks !!

    public class IntCompl {
        public String getEqualSumSubstring_com(String s)
        {
            int j;
            int num=0;
            int sum = 0;
            int m=s.length();
            //calculate String array Length
            for (int i=m;i>1;i--)
            {
                sum = sum + m;
                m=m-1;
            }
            String [] d = new String[sum];
            int k=0;
            String ans = "NULL";
            //Extract strings
            for (int i=0;i<s.length()-1;i++)
            {
            for (j=s.length();j>=i+1;k++,j--)
            {
                num = k;
                d[k] = s.substring(i,j);
            }
            k=num+1;
            }
            //Sort strings in such a way that the longest strings precede...
            for (int i=0; i<d.length-1; i++)
            {
                for (int h=1;h<d.length;h++)
                {
                if (d[i].length() > d[h].length())
                 {
                    String temp;
                    temp=d[i];
                    d[i]=d[h];          
                    d[h]=temp;
                 }
                }       
            }
            // Look for the Strings with array size 2*N (length in even number) and such that the 
            //the sum of left N numbers is = to the sum of right N numbers.
            //As the strings are already in decending order, longest string is searched first and break the for loop once the string is found.
            for (int x=0;x<d.length;x++)
            {
                int sum1=0,sum2=0;
                if (d[x].length()%2==0 && d[x].length()<49)
                {
                    int n;
                    n = d[x].length()/2;
                    for (int y=0;y<n;y++)
                    {
                        sum1 = sum1 + d[x].charAt(y)-'0';
                    }
                    for (int y=n;y<d[x].length();y++)
                    {
                        sum2 = sum2 + d[x].charAt(y)-'0';
                    }
                    if (sum1==sum2)
                    {
                        ans = d[x];
                        break;
                    }
                }
            }
                return ans;
            }
        }

下面是解决这个问题的完整Java程序。复杂度为O(n^3)这个可以在O(n^2)内解决。对于O(n^2)复杂度解,请参考此链接

import java.util.Scanner;
import static java.lang.System.out;
 public class SubStringProblem{
  public static void main(String args[]){
 Scanner sc = new Scanner(System.in);
 out.println("Enter the Digit String:");
 String s = sc.nextLine();
 int n = (new SubStringProblem()).getEqualSumSubString(s);
 out.println("The longest Sum SubString is "+n);
 }
    public int getEqualSumSubString(String s){
 int N;
 if(s.length()%2==0)
 {
    //String is even
    N = s.length();     
 }
 else{ 
    //String is odd
    N=s.length()-1;
 }
 boolean flag =false;
 int sum1,sum2;
 do{    
    for(int k=0;k<=s.length()-N;k++){   
        sum1=0;
        sum2=0;
        for(int i =k,j=k+N-1;i<j;i++,j--)
        {   
            sum1=sum1 + Integer.parseInt(s.substring(i,i+1));
            sum2+=Integer.parseInt(s.substring(j,j+1));
        }
        if(sum1==sum2){
        return N;
        }
    }   
    N-=2;
 flag =true;
}while(N>1);
return -1;
}
}

这两行数字48的理由是什么?

for(int k=0;k<temp/2;k++)
{
    leftSum=leftSum+tempString[k]-48;
    rightSum=rightSum+tempString[k+(temp/2)]-48;
}

我只是过于好奇,想听听背后的原因,因为我有一个类似的解决方案,但没有48,它仍然有效。然而,我把48加起来,仍然得到了正确的答案。

解决方案很简单。O (n * n)。S -输入字符串。

var longest = 0;
for (var i = 0; i < s.length-1; i++) {
    var leftSum = rightSum = 0;
    for (var j = i, k = i+1, l = 2; j >=0 && k < s.length; j--, k++, l+=2) {
        leftSum += parseInt(s[j]);
        rightSum += parseInt(s[k]);
        if (leftSum == rightSum && l > longest) {
            longest = l;
        }
    }
}
console.log(longest);