题意理解

在字符串中找到长度最大的数字子串,如果有多个数字子串长度相等且最大,则按其在字符串中的顺序一次输出。数字子串指由数字连续构成的子串。

方法一

模拟,双指针。从左到右扫描字符串,并重复一下操作:
1、遇到一个数字字符,位置为i,暂停;
2、从i开始往后扫描,直到遇到非数字字符,位置为j;
3、计算当前发现的数字子串长度,并更新;
4、把j的值赋给i,继续扫描。

模拟过程如下: alt

具体代码如下:

#include<iostream>
#include<string>
#include<vector>

using namespace std;

int main()
{
    string s;
    while (cin>>s)
    {
        int i=0;
        int maxm = 0;
        //记录最长数字子串的起始位置
        vector<int> index;
        while (i<s.size())
        {
            if ('0'<=s[i] && s[i]<='9')
            {
                int j = i + 1;
                //找到一个连续的数字子串
                while ('0'<=s[j] && s[j]<='9') j++;
                //如果和当前最大长度相等,则记录子串的第一个字符
                if ((j-i)==maxm)
                {
                    index.push_back(i);
                }
                //如果大于当前最大长度,则更新
                if ((j-i)>maxm)
                {
                    maxm = j - i;
                    index.clear();
                    index.push_back(i);
                }
                i = j + 1;
            }
            else i++;
        }
        for (int h=0;h<index.size();h++)
        {
            for (int k=0;k<maxm;k++) cout<<s[index[h]+k];
        }
        cout<<','<<maxm<<endl;
    }
    return 0;
}

时间复杂度: O(N)O(N)。虽然是多重循环,但是字符串中的每个字符至多被扫描一次。 空间复杂度: O(N)O(N)。使用了一个index数组记录可能的数字子串的起始位置,最坏情况下需要记录N/2次,例如“a1a1a1a1a1a1”。

方法二

先将所有的非数字的字符替换成某个特定字符,例如‘.’,再使用strtok()方法将其进行分隔,最后挑选出最长的数字子串。

具体代码如下:

#include<iostream>
#include<string>
#include<vector>
#include<string.h>
#include<stdio.h>
#include<cstdlib>

using namespace std;

int main()
{
    char s[200];
    vector<string> num;
    while (cin>>s)
    {
        //替换
        for (int i=0;i<strlen(s);i++)
        {
            if (s[i]<'0' || '9'<s[i]) s[i] = '.';
        }
        int maxm = 0;
        const char *p = ".";
        char *split;
        //使用strtok分割字符串
        split = strtok(s, p);
        while (split)
        {
            //判断子串的长度
            if (strlen(split)==maxm)
                num.push_back(string(split));
            if (strlen(split)>maxm)
            {
                maxm = strlen(split);
                num.clear();
                num.push_back(string(split));
            }
            split = strtok(NULL, p);
        }
        for (int i=0;i<num.size();i++)
            cout<<num[i];
        cout<<','<<maxm<<endl;
    }
    return 0;
}

时间复杂度: O(N)O(N)。在替换字符时遍历了一遍字符串。 空间复杂度: O(N)O(N)。使用了一个num数组记录下可能的最长数字子串。