您的位置:首页 > 理论基础 > 数据结构算法

Tekson的数据结构程序10——字符串

2009-11-09 22:39 274 查看

10. 字符串

(1)求一个字符串中连续出现次数最多的子串

#include "stdafx.h"

#include <iostream>

#include <string>

using namespace std;

int main()

{

string str = "abcbcbcabc";

size_t i, j, k;//用于控制循环

size_t count, maxcount=1;//count用于计数,最小为;maxcount用于记录重复的最大次数,最小为

string subStr;

size_t len = str.size();

for(i=0; i<len; ++i)

{

for(j=i+1; j<len; ++j)//每一次第二层循环结束后都要对maxcount进行更新

{

count = 1;//每次内循环时都要归为

if(str.substr(i, j-i) == str.substr(j, j-i))//判断第一次连续重复的字符串的出现

{

++count;//只要有连续重复的字符串出现,则count至少为

for(k=j+(i-i); k<len && str.substr(i, j-i)==str.substr(k, j-i); ++k)

//寻找后续重复的字符串并计数,这一步只能在已经有重复子串的前提下进行,

//因此应该在第三层循环中进行

++count;

}

if(count > maxcount)

{

maxcount = count;

subStr = str.substr(i, j-i);

}

}

}

cout << "The sub-string \"" << subStr << "\"'s times is " << maxcount << endl;

}

(2)找出字符串中重复出现的最长子串,并输出该子串及其首字符的位置

#include "stdafx.h"

#include <iostream>

#include <string>

using namespace std;

int main()

{

string str = "eabcdbcebcfabc";//结果为abc's index is 1

/*当string str = "ddd"时,结果为dd's index is 0,可见,两个相同的子串可以彼此重叠, 但这时一定是若干个相同字符组成的*/

size_t i, j;//用于控制循环

size_t p1, p2;//pos用于存储重复字符串的位置;p1和p2用于存储正向和逆向搜索子串的位置

string subStr;

size_t len = str.size();

for(i=len-1; i>1; --i)//i为子串的长度,这里并没有强调一定要两个子串不重叠,故子串的最大长度可以为n-1

{

for(j=0; j<len && j+i<=len; ++j)//j+i<=len保证了以j为起始点i为子串长度的子串不会超出原字符串

{

subStr = str.substr(j, i);

p1 = str.find(subStr);

p2 = str.rfind(subStr);

if(p1 != p2)//表明有重复的子串出现,且第一次满足此条件的一定是最长的子串

{

cout << subStr << "\'s index is " << p1 << endl;

return 0;//当运行当此if子句时,则说明已经完成任务,故返回

}

}

}

}

(3)编写strstr()函数,返回值是字符串中子串的位置及其以后的所有字符

#include "stdafx.h"

#include <assert.h>

#include <iostream>

using namespace std;

const char *strstr(const char *str, const char *strSearch)

{

assert(str!=NULL && strSearch!=NULL); //【注】assert函数需要头文件assert.h

int i, j;//内外层循环索引

for(i=0; str[i]!='\0'; ++i)

{

for(j=0; strSearch[j]!='\0' && str[i+j]==strSearch[j]; ++j);

if('\0' == strSearch[j])

return str + i;

}

return NULL;

}

int main()

{

char *str="abcdbcebcfabc", *strSearch="fa";

cout << strstr(str, strSearch) << endl;//输出:fabc

}

(4)字符串倒置问题

① 倒置字符串但保持单词自身的顺序

【思想】采用<csting>头文件中的strtok()函数先将字符串中的单词(字符串的单词被看作是通过’ ’、’,’、’|’、’.’、’;’、’-’等符号被隔开的子字符串)提取出来,然后分别将其存入到list<string>中,最后通过<algorithm>中的copy算法将list的各字符串按逆序打印出来,于是便可以达到目的。

#include <stdafx.h>

#include <cstring>

#include <string>

#include <iostream>

#include <vector>

#include <algorithm>

using namespace std;

int main()

{

char str[]=", WXL, ,is, ,,,really-a,,,Niu|man. | ";

const char *delims = " ,-|";//delimiter:分隔符,定界符

vector<string> vstr;

// Establish string and get the first token:

char *token = strtok(str, delims);

while( token != NULL )

{

vstr.push_back(token);

// Get next token:

token = strtok( NULL, delims); //NULL is the starting index of the next token substring

}

for(vector<string>::reverse_iterator iter=vstr.rbegin(); iter!=vstr.rend(); ++iter)

//【注】这里要将iter声明为reverse_iterator,因为rbegin函数返回的是reverse_iterator。

cout << *iter << " ";

cout << endl;

//输出也可以通过一条语句来完成:copy(vstr.rbegin(), vstr.rend(), ostream_iterator<string>(cout, " "));

}

② 倒置字符串中的单词的字符顺序但保持单词间的顺序

【思想】采用<csting>头文件中的strtok()函数先将字符串中的单词(字符串的单词被看作是通过’ ’、’,’、’|’、’.’、’;’、’-’等符号被隔开的子字符串)提取出来,然后分别将其存入到vector<string>中,然后对vector中每个元素进行排序,最后通过<algorithm>中的copy算法将vector的各字符串按逆序打印出来,于是便可以达到目的。

#include <stdafx.h>

#include <cstring>

#include <string>

#include <iostream>

#include <vector>

#include <algorithm>

using namespace std;

int main()

{

char str[]="pots & pans";

const char *delims = " \t,.;";

vector<string> vstr;

// Establish string and get the first token:

char *token = strtok(str, delims);

while( token != NULL )

{

vstr.push_back(token);

// Get next token:

token = strtok( NULL, delims); //NULL is the starting index of the next token substring

}

// Sort for every sub-string

for(size_t i=0; i<vstr.size(); ++i)

{

for(string::size_type j=0,k=vstr[i].size()-1; j<k; ++j,--k)

swap(vstr[i][j],vstr[i][k]);

}

copy(vstr.begin(), vstr.end(), ostream_iterator<string>(cout, " "));

return 0; //it can be omited

}

(5)转换字符串格式为:原来字符串里的字符+该字符串连续出现的个数,例如字符串:1233422222,转化为1121314125

#include <stdafx.h>

#include <string>

#include <iostream>

using namespace std;

int main()

{

char str[]="1233422222";

size_t i, j, k=0;//i,j为循环控制索引,而k为新数组的索引项

size_t len = strlen(str);

char *newStr = new char [2*len+1];//2*len+1为最坏情况(即无连续相同字符存在)下所占用的空间

size_t n;

for(i=0; i<len; i+=n)

{

for(j=i+1; j<len && str[j]==str[i]; ++j);

newStr[k++] = str[i];

n = j-i;

newStr[k++] = n + '0';//【注】这里必须为n + '0',不能缺少'\0'

}

newStr[k] = '\0';

cout << newStr << endl;

}

(6)计算4000000000以内的最大的那个f(n)=n的值,函数f的功能是统计所有从0到n之间所有含有数字1的数字和

#include <stdafx.h>

#include <string>

#include <iostream>

using namespace std;

int fun(const int n)

{

char str[11];

int i, j;

int num = 0;//存储n中的个数

int len;//len为转换后的字符串的长度,也即原整数的位数

for(i=1; i<=n; ++i)

{

ultoa(i, str, 10); //ultoa函数将unsigned int转化为char *型字符串

len = strlen(str);

for(j=0; j<len; ++j)

{

if('1' == str[j])

++num;

}

}

return num;

}

int main()

{

unsigned int i;//int的范围为-2^31~2^31-1,即-2147483648~2147483647,因此,应该声明为unsigned int

for(i=4000000000; i>=1; --i)

if(i==fun(i))

{

cout << i << endl;

return 0;

}

cout << i << endl;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐