String相关操作

1.求字符串中连续出现最多的字串

pair<string, int> substring(const string& str)
{
    int i, j, k, len = str.length(), count, maxcount = 1;
    string substr;
    vector<string> substrs;

    //存储所有的子字符串
    for ( i = 0; i < len; ++i)
    {
        substrs.push_back(str.substr(i, len - i));
    }

    for ( i = 0; i < len; ++i)
    {
        for ( j = i + 1; j < len; ++j)
        {
            count = 1;
            if (substrs[i].substr(0,j-i)==substrs[j].substr(0,j-i))
            {
                ++count;
                for (k = j + (j - i); k < len; k += j - i)
                {
                    if (substrs[i].substr(0, j - i) == substrs[k].substr(0, j - i))
                    {
                        ++count;
                    }
                    else
                        break;
                }
                if (count>maxcount)
                {
                    maxcount = count;
                    substr = substrs[i].substr(0, j - i);
                }
            }
        }
    }

    return make_pair(substr, maxcount);
}

大致理解,但是有没有更佳的解法呢?

 

2.求字符串中出现的相同且长度最长的字符串,输出首字符的位置

pair<string, int> substring(const string& str)
{
    string substr{""};
    int i, j, left, right, len = str.length();

    for (i = len - 1; i > 1; --i)
    {
        for ( j = 0; j < len; ++j)
        {
            if (j + i < len)
            {
                left = right = 0;
                substr = str.substr(j, i);

                left = str.find(substr);
                right = str.rfind(substr);

                if (left!=right)
                {
                    return make_pair(substr,left);
                }
            }
            else 
                break;
        }
    }

    return make_pair(substr,0);
}

从大字符串进行拆分,两边结合搜索比将所有子字符串拆分寻找效率高。

至于调用库函数,是比较方便的选择。

 

3.重写strstr,且返回朱传忠字符子串位置以后的所有字符

const char* strstr_(const char* src,const char* substr)
{
    const char* tmp;
    while (*src!='0')
    {
        if (*src==*substr)
        {
            tmp = substr;
            while (*src++==*tmp++)
            {
                if (*tmp=='\0')
                {
                    return src;
                }
            }
        }
        else
            *src++;
    }

    return nullptr;
}

注意其中为什么使用tmp代替字串,因为可能会重复比较,所以需要字串的值持续存在。

 

3.将字符串中的单词进行倒置,标点符号不倒换。“i come from nanjing!”->"nanjing! from come i".

void transfer(char* dst,const char* src)
{
    bool sign = false;
    int i, j, k, left, right, num = 0, len = strlen(src);

    for ( i = 0; i <= len ; i++)
    {
        if (' ' != src[i] && '\0' != src[i]) //排除空格
        {
            if (sign)
            {
                right++;
            }
            else
            {
                sign = true;
                left = right = i;
            }
        }
        else
        {
            if (sign)
            {
                sign = false;
                dst[len -1- i] = src[i];
                for ( j = left, k = len-1-right; j <= right; j++, k++)
                {
                    dst[k] = src[j];
                }
                left = right = 0;
            }
            else
            {
                dst[len-1 - i] = src[i];
            }
        }
    }
}

个人觉得比程序员面试宝典的方法更为简洁,不过其方法较容易操作。后续可以补上程序员面试宝典上的操作。

 4.程序员面试宝典上一道填空题,移动字符串内容,将字符串的倒数n个字符移动到字符串前面,仅能在while中填空

void righttransfer(char *str,int n)
{
	int i = 0, len = strlen(str);
	if (n > len) n = len;

	while (len - n > 0 || (n = 0) != 0)
	{
		for (i = 0, str[len] = str[0], ++n; i < len; i++)
			str[i] = str[i + 1];
	}

	str[len - n] = '\0';
}

这里面的巧妙之处就在于(n = 0) != 0操作,当字符串移动结束,最后一位'\0'因为移动被字符覆盖了,现在需要重新赋值。

而n已经被修改了,这时候就要重新初始化了,利用||特性,前面为真时直接跳过,此时移动到结尾,len-n为false,则跳到后半部分。

n被赋值为0,即n!=0操作为false,跳出循环,完美。

posted @ 2015-07-25 18:19  从此寂静无声  阅读(158)  评论(0编辑  收藏  举报