ASCII:(American Standard Code for Information Interchange)计算机常用字符标准编码码,用7位二进制数表示一个字符,总共可表示128个字符,后拓展ASCII码由8位二进制表示一个字符,总共可以表示256个字符。
Unicode: 统一码、万国码或单一码,通常用2个字节,16位二进制表示一个字符,总共可表示2^16幂个字符,前256个字符和ASCII码兼容。
UTF-n:(Unicode Transformation Format),正对Unicode的一种可变长度字符编码,UTF-8:最小使用8个二进制编码(1个字节编码或2或3字节编码),UTF-16:最小使用16个二进制编码(2个字节或4个字节)其都是Unicode编码方案。
利用串的一些自定义函数方法,比较字符串string1中是否有与string2相同的子串,如有则返回在pos后第一次出现相同子串的位置:
def str_length(string): # 利用循环读数,获取字符串长度
length = 0
for i in string:
if i != '':
length += 1
return length
def get_substring(str1, pos, length): # 获取固定位置后定长子串
l1 = str_length(str1)
if 0 <= length <= l1 - pos + 1:
substring = str1[(pos - 1):(pos + length - 1)]
return substring
def comp_string(str1, str2): # 利用循环字符串每一位是否相同
l1 = str_length(str1)
l2 = str_length(str2)
if l1 == l2:
count = 0
for i in range(l1):
if str1[i] == str2[i]:
count += 1
else:
break
if count == l1:
return 1
else:
return -1
else:
return -1
def index(string1, string2, pos): # 比较string1中是否有string2子串,如有则返回pos后第一次出现位置
l1 = str_length(string1)
l2 = str_length(string2)
pos_temp = pos
while 0 <= pos_temp <= l1 - l2 + 1:
sub = get_substring(string1, pos_temp, l2)
result = comp_string(sub, string2)
if result > 0:
return '字符串\'{}\'与字符串\'{}\',在位置{}后第一次相同位置为{}'.format(string1, string2, pos, pos_temp)
else:
pos_temp += 1
if pos_temp > l1 - l2 + 1:
return '字符串\'{}\'与字符串\'{}\'无相同子串'.format(string1, string2)
if __name__ == '__main__':
test_a = 'abcedabcdeddffee'
test_b = 'ddff'
test_c = 'ddfg'
pos = 4
print(index(test_a, test_b, pos))
当然利用python中的len(),compare()就可获取字符串长度,比对字符串是否相同,为了更清楚理解其原理,改用自定义函数。
模式匹配: 在子串中的定位操作,不考虑串的其他操作,仅用基本的字符遍历寻找子串位置:
def index(string1, string2, pos):
l1 = len(string1)
l2 = len(string2)
pos_temp = pos
j = 0
while l1 - l2 - pos_temp + 1 >= 0:
if string1[pos_temp] == string2[j]:
pos_temp += 1
j += 1
else:
pos_temp += 1
j = 0
if j >= l2:
pos_temp = pos_temp - l2 + 1
return '字符串\'{}\'与字符串\'{}\',在位置{}后第一次相同位置为{}'.format(string1, string2, pos, pos_temp)
else:
return '字符串\'{}\'与字符串\'{}\'无相同子串'.format(string1, string2)
if __name__ == '__main__':
test_a = 'abcedabcdeddffee'
test_b = 'ddff'
test_c = 'ddfg'
pos = 4
print(index(test_a, test_b, pos))
时间复杂度:O[(L1-L2+1) * L2]
由克努特—莫里斯—普拉特(D.E.Knuth,J.H.Morris,V.R.Pratt)提出的KMP模式匹配算法,根据匹配子串结构重复情况,在第一次匹配后减少不必要的重复性比对过程。根据子串结构得出next[]数组:
next[] 数组原表示当前位置匹配前缀与匹配后缀的长度,以下程序get_next() 获取当前位置字符串匹配过程中不相等时需要回溯的位置,get_nextval() 作为next的一种升级为降低特殊子串,如’aaaaax’的计算复杂度,详细推导过程见《大话数据结构》p142
Python代码实现:
def get_next(string): # 计算当前字符串的next数组
length = len(string)
next = []
next.append(0)
i = 1
j = 0
while i < length:
if j == 0 or string[i - 1] == string[j - 1]:
i += 1
j += 1
next.append(j)
else:
j = next[j - 1] # 字符不相等,j值回溯
return next
def get_nextval(string):
l1 = len(string)
j = 0
i = 1
nextval = []
nextval.append(0)
while i < l1:
if j == 0 or string[i - 1] == string[j - 1]:
j += 1
i += 1
if string[i - 1] != string[j - 1]:
nextval.append(j)
else:
nextval.append(nextval[j - 1])
else:
j = nextval[j - 1]
return nextval
def index_kmp(string1, string2, pos):
i = pos
j = 1
next = get_next(string2) # 获取next数组
# next = get_nextval(string2) # 获取升级后的nextval数组
l1 = len(string1)
l2 = len(string2)
while i < l1 and j < l2:
if j == 0 or string1[i - 1] == string2[j - 1]:
j += 1
i += 1
else:
j = next[j - 1] # next数组,回溯j值
if j >= l2:
return '字符串{}与子串{},在{}后第一次相同位置为{}'.format(string1, string2, pos, i + 1 - l2)
else:
return 'No match substring!'
if __name__ == '__main__':
test_a = 'abcedabcdeddffee'
test_b = 'ddff'
test_c = 'aaaabcde'
test_d = 'aaaax'
pos = 4
print(index_kmp(test_a, test_b, pos))
# print(index_kmp(test_c, test_d, pos))
KPM 模式匹配算法作为理解 index 函数有着重要作用。
C++代码实现:
#include
using namespace std;
//KMP算法查找匹配字符串
void get_next(string T, int *next) //获取next数组
{
int i = 1;
int j = 0;
next[i] = 0;
while (i < T[0])
{
if (j == 0 || T[i] == T[j])
{
i++;
j++;
next[i] = j;
}
else
j = next[j];
}
}
//改进后的next数组
void get_nextval(string T, int* nextval)
{
int i = 1;
int j = 0;
nextval[i] = 0;
while (i < T[0])
{
if (j == 0 || T[i] == T[j])
{
i++;
j++;
if (T[i] != T[j])
nextval[i] = j;
else
nextval[i] = nextval[j];
}
else
j = nextval[j];
}
}
string str:生成空字符串
string s(str):生成字符串为str的复制品
string s(str, strbegin,strlen):将字符串str中从下标strbegin开始、长度为strlen的部分作为字符串初值
string s(cstr, char_len):以C_string类型cstr的前char_len个字符串作为字符串s的初值
string s(num ,c):生成num个c字符的字符串
string s(str, stridx):将字符串str中从下标stridx开始到字符串结束的位置作为字符串初值
size()和length():返回string对象的字符个数,他们执行效果相同。
max_size():返回string对象最多包含的字符数,超出会抛出length_error异常
capacity():重新分配内存之前,string对象能包含的最大字符数
int compare(const string &s) const;
//与字符串s比较int compare(const char *s) const;
//与字符串s比较= 返回 0
> 返回 1
< 返回 -1
string& insert(int pos, const char* s);
//插入字符串string& insert(int pos, const string& str);
//插入字符串string& insert(int pos, int n, char c);
//在指定位置插入n个字符cvoid test4()
{
string str = "hello";
str.insert(1, "111");
string s1;
// 尾插一个字符
s1.push_back('a');
s1.push_back('b');
s1.push_back('c');
}
void test5()
{
// 方法一:append()
string s1("abc");
s1.append("def");
cout<<"s1:"<<s1<<endl; // s1:abcdef
// 方法二:+ 操作符
string s2 = "abc";
/*s2 += "def";*/
string s3 = "def";
s2 += s3.c_str();
cout<<"s2:"<<s2<<endl; // s2:abcdef
}
string& erase(int pos, int n = npos);
//删除从Pos开始的n个字符
void test6()
{
string s1 = "123456789";
s1.erase(s1.begin()+1); // 结果:13456789
s1.erase(s1.begin()+1,s1.end()-2); // 结果:189
s1.erase(1,6); // 结果:189
}
功能描述:
函数原型:
int find(const string& str, int pos = 0) const;
//查找str第一次出现位置,从pos开始查找int find(const char* s, int pos = 0) const;
//查找s第一次出现位置,从pos开始查找int find(const char* s, int pos, int n) const;
//从pos位置查找s的前n个字符第一次位置int find(const char c, int pos = 0) const;
//查找字符c第一次出现位置int rfind(const string& str, int pos = npos) const;
//查找str最后一次位置,从pos开始查找int rfind(const char* s, int pos = npos) const;
//查找s最后一次出现位置,从pos开始查找int rfind(const char* s, int pos, int n) const;
//从pos查找s的前n个字符最后一次位置int rfind(const char c, int pos = 0) const;
//查找字符c最后一次出现位置string& replace(int pos, int n, const string& str);
//替换从pos开始n个字符为字符串strstring& replace(int pos, int n,const char* s);
//替换从pos开始的n个字符为字符串svoid test01()
{
//查找
string str1 = "abcdefgde";
int pos = str1.find("de");
if (pos == -1)
{
cout << "未找到" << endl;
}
else
{
cout << "pos = " << pos << endl;
}
pos = str1.rfind("de");
cout << "pos = " << pos << endl;
}
void test02()
{
//替换
string str1 = "abcdefgde";
str1.replace(1, 3, "1111");
cout << "str1 = " << str1 << endl;
}
#include
void test8()
{
string s = "cdefba";
sort(s.begin(),s.end());
cout<<"s:"<<s<<endl; // 结果:abcdef
}
#include
#include
using namespace std;
int main()
{
string s = "ABCDEFG";
for( int i = 0; i < s.size(); i++ )
{
s[i] = tolower(s[i]); //转换为小写
}
cout<<s<<endl;
return 0;
}
test2()
{
string s = "ABCDEFG";
string result;
result.resize(s.size()); //不可缺,提前预留空间
transform(s.begin(), s.end(), result.begin(), tolower); //将转换后的结果存入result
transform(s.begin(), s.end(), s.begin(), tolower); //直接将s转化为小写
cout << "result:" << result << endl;
cout << "s:" << s << endl;
}
包含头文件
序号 | 函数&描述 |
---|---|
1 | int isalnum(int c),该函数检查所传的字符是否是字母和数字。 |
2 | int isalpha(int c),该函数检查所传的字符是否是字母。 |
3 | int isdigit(int c),该函数检查所传的字符是否是十进制数字。 |
4 | int islower(int c),该函数检查所传的字符是否是小写字母。 |
5 | int isupper(int c),该函数检查所传的字符是否是大写字母。 |
6 | int isspace(int c),该函数检查所传的字符是否是空白字符。 |