July著《编程之法》-字符串

在看博客的时候发现July编著的《编程之法  面试和算法心得》非常适合自己,故果断买一本仔细研读学习,在此做个记录并实时更新,以备后续之用,再次感谢July老师,非常不错的一本书籍,推荐购买,感谢!!!

免费高清PDF带书签July编著的《编程之法  面试和算法心得》【建议买一本,方便查看】

https://pan.baidu.com/s/154wjouhTjAFxNjMQZEY01Q   提取码:k3z9 

PS:使用编程环境Window7下的VS2015

第一章字符串

1.1字符串的旋转

/*暴力移位法*/
#include
using namespace std;
#include 
const int N = 20;

//打印字符串
void print(char *a)
{
	int len = strlen(a);
	for (int i = 0; i < len; i++)
	{
		cout << a[i];
	}
	cout << "\n";
}
//将数组a中前n个元素移动到后面
void move(char *a, int n)
{
	int len = strlen(a);
	int i;
	char ch;
	while (n--)
	{
		ch = *(a + 0);//暂时存放第一个元素
		for (i = 0; i < len - 1; i++)
		{
			a[i] = a[i + 1];
		}
		a[i] = ch;
	}
}

int main()
{
	char a[N] = "abcdefghi";
	int n;//需要移动的字符数量
	//打印原始字符串
	cout << "打印原始字符串为:";
	print(a);

	//移动后的字符串
	cout << "请输入需要移动字符数量:n = ";
	cin >> n;
	move(a, n);
	print(a);

	system("pause");
	return 0;
}
/*三步反转法*/
#include
using namespace std;
#include 
const int N = 20;

//打印字符串
void print(char *a)
{
	int len = strlen(a);
	for (int i = 0; i < len; i++)
	{
		cout << a[i];
	}
	cout << "\n";
}
//反转字符串,从字符串的第from到to进行反转
void Reverse(char *a, int from, int to)
{
	char ch;
	while (from < to)
	{
		ch = a[from];
		a[from++] = a[to];
		a[to--] = ch;
	}
}
int main()
{
	char a[N] = "abcdefghi";
	int n;//需要移动的字符数量
	int len = strlen(a);
	//打印原始字符串
	cout << "打印原始字符串为:";
	print(a);

	//移动后的字符串
	cout << "请输入需要移动字符数量:n = ";
	cin >> n;
	Reverse(a, 0, n-1);//先反转第一组
	Reverse(a, n, len-1);//再反转第二组
	Reverse(a, 0, len - 1);//最后整体反转
	print(a);

	system("pause");
	return 0;
}

课后习题之单词反转

分析:该题同样是字符串的反转问题,和前面例题不同的是不是单个字符的反转,而是将某些字符串当做一个整体进行反转,所以难点在于如何将某些字符串当做之前例题讲解的单个字符就OK了。想到这里我就想到了字符串数组,问题迎刃而解^_^。


#include
using namespace std;
#include 
const int N = 20;

//打印字符串
void print(string a[],int len)
{
	for (int i = 0; i < len; i++)
	{
		cout << a[i] << ' ';
	}
	cout << "\n";
}
//反转字符串【以独立字符串为整体进行反转】
void Reverse(string a[], int from, int to)
{
	string str;
	while (from < to)
	{
		str = a[from];
		a[from++] = a[to];
		a[to--] = str;
	}
}

int main()
{
	string a[N];
	char ch;
	int i = 0;
	cout << "请输入原始字符串:";
	while ((ch = cin.peek()) != '\n')//cin.peek()函数仅仅是查看,不取出;此处换为cin.get()出错
	{
		cin >> a[i];
		i++;
	}
	cout << "打印原始的字符串:";
	print(a, i);
	//反转字符串
	Reverse(a, 0, i-1);
	cout << "打印反转后的字符串:";
	print(a, i);

	system("pause");
	return 0;
}

1.2字符串的包含

July著《编程之法》-字符串_第1张图片

求解字符串的长度方法

当a为字符数字时,其真实长度len = strlen(a);当a为string类型时,其真实长度为len = a.length()

sort()函数使用方法

https://blog.csdn.net/shiyideliutang/article/details/83010067

埃氏筛法求解素数问题

https://blog.csdn.net/holly_z_p_f/article/details/85063174

//暴力轮询法
#include
using namespace std;
#include 

//判断字符串a中是否全部包含字符串b中的字符
bool StringContain(string a, string b)
{
	int n = 0;//存放两个字符串相同的字符数目
//求解字符串的长度方法
//当a为字符数字时,其真实长度len = strlen(a)
//当a为string类型时,其真实长度为len = a.length()
	int len1 = a.length(), len2 = b.length();
	cout << "字符串a的长度为:" << len1;
	cout << ",字符串b的长度为:" << len2 << "\n";
	for (int i = 0; i < len2; i++)
	{
		for (int j = 0; j < len1; j++)
		{
			if (b[i] == a[j])
			{
				n++;
				break;
			}
		}
	}
	if (n == len2)
		return true;
	return false;
}

int main()
{
	string a, b;
	cout << "请输入字符串a:";
	cin >> a;
	cout << "请输入字符串b:";
	cin >> b;
	if (StringContain(a, b))
		cout << "true" << "\n";
	else
		cout << "false" << "\n";

	system("pause");
	return 0;
}
//排序后轮询法
#include
using namespace std;
#include 
#include //排序函数sort()

//判断字符串a中是否全部包含字符串b中的字符
bool StringContain(string a, string b)
{
	sort(a.begin(), a.end());//对字符串a今次那个从小到大排序
	sort(b.begin(), b.end());
	cout << "按照从小到大的顺序排序后的字符串a为:" << a
		<< ",字符串b为:" << b << "\n";
	for (int pb = 0, pa = 0; pb < b.length(); pb++)
	{
		while ( (pa < a.length()) && (a[pa] < b[pb]) )
		{
			pa++;
		}

		if ( (pa >= a.length()) || (a[pa] > b[pb]))
			return false;
	}

	return true;;
}

int main()
{
	string a, b;
	cout << "请输入字符串a:";
	cin >> a;
	cout << "请输入字符串b:";
	cin >> b;
	if (StringContain(a, b))
		cout << "true" << "\n";
	else
		cout << "false" << "\n";

	system("pause");
	return 0;
}
//素数相乘法【该方法有缺陷:素数相乘容易溢出】
#include
using namespace std;
#include 

//埃氏筛法求解素数
void get_primer(int primer[], int n)
{
	const int Max = 200;//定义最大200的空间,即求解200以内的素数
	//先假设都为素数
	bool is_primer[Max];//这种方式初始化不行bool is_primer[Max] = { true };
	memset(is_primer, true, Max);
	is_primer[0] = is_primer[1] = false;//数字0,1不是素数
	for (int i = 2; i < Max; i++)//从数字2开始筛选
	{
		if (is_primer[i])
		{
			for (int j = 2 * i; j < Max; j += i)
				is_primer[j] = false;
		}
	}
	//将筛选后得到的素数存储在素数对应表中,需要存储的数量为n
	int j = 0;
	for (int i = 2; i < Max; i++)
	{
		if (is_primer[i])
		{
			primer[j++] = i;
			if (j == n)
				break;
		}
	}
	//打印输出得到的素数表
	cout << "打印输出得到的素数对应表为:";
	for (int i = 0; i < j; i++)
	{
		cout << primer[i] << " ";
	}
	cout << "\n";
}

//判断字符串a中是否全部包含字符串b中的字符
bool StringContain(string a, string b)
{
	long long sum1 = 1;//这里最开始定义int类型,但是有可能会溢出,造成运算结果出错
					   //建立素数对应表
	int primer[26];
	get_primer(primer, 26);
	//求解字符串a中字符对应素数的乘积
	for (int i = 0; i < a.length(); i++)
	{
		int x = primer[a[i] - 'A'];
		if (sum1 % x)//目的是过滤重复的字符,可以没有这个判断语句
		{
			sum1 = sum1 * x;
		}
	}
	//判断字符串b对应的素数是否为a对应素数乘积的因子
	for (int j = 0; j < b.length(); j++)
	{
		int y = primer[b[j] - 'A'];
		if (sum1 % y)//有余数的话,说明字符串b中含有的字符在a中没有
			return false;
	}

	return true;
}

int main()
{
	string a, b;
	cout << "请输入字符串a:";
	cin >> a;
	cout << "请输入字符串b:";
	cin >> b;
	if (StringContain(a, b))
		cout << "true" << "\n";
	else
		cout << "false" << "\n";

	system("pause");
	return 0;
}
//位运算法:字符的比较转化为二进制位运算
#include
using namespace std;
#include 

//判断字符串a中是否全部包含字符串b中的字符
bool StringContain(string a, string b)
{
	int hash = 0;
	for (int i = 0; i < a.length(); i++)
	{
		hash |= (1 << (a[i] - 'A'));//将1左移(a[i] - 'A')位
	}

	for (int i = 0; i < b.length(); i++)
	{
		if ((hash & (1 << (b[i] - 'A'))) == 0)
			return false;
	}

	return true;
}

int main()
{
	string a, b;
	cout << "请输入字符串a:";
	cin >> a;
	cout << "请输入字符串b:";
	cin >> b;
	if (StringContain(a, b))
		cout << "true" << "\n";
	else
		cout << "false" << "\n";

	system("pause");
	return 0;
}

课后习题之变位词

方法一思路分析:用两个数组分别统计两个字符串里每个字符出现的个数,如果完全一致,则是变位词,否则不是。

#include 
using namespace std;
#include 

//将string类型转化为char*类型
//这里采用指针引用[*&p]的方式改变原来指针,如果改为*p则无法改变原来的指针【本质是值传递】
bool string_char(string str, char *&p)
{
    int len = str.length();
    p = new char[len*2];//开辟足够大的内存存储
    int n = str.copy(p, len, 0);
    p[len] = '\0';
    if(n == len)
        return true;

    return false;
}

//统计字符串中各个字符的个数,并存储在数组中
bool Search(string s, string p)
{
    int a[128], b[128];
    memset(a, 0, sizeof(a));//全部填充为0
    memset(b, 0, sizeof(b));
    char *sp,*pp;
    string_char(s,sp);
    string_char(p,pp);

    //统计库中字符的个数
    while( (*sp) != '\0')
    {
        a[*sp]++;
        sp++;
    }
    //统计目标串中字符的个数
    while( (*pp) != '\0')
    {
        b[*pp]++;
        pp++;
    }

    return (0 == memcmp(a,b,sizeof(a)));//将数组a,b前sizeof(a)进行比较
}

int main()
{
    string s[20];
    string p;
    int n = 0,num = 0;//存放目标字符串在字符串中的位置以及总个数
    cout << "请输入字符串库:";
    char ch;
    int i = 0;
    while( (ch = cin.peek()) != '\n')//向字符串库中存储字符串
    {
        cin >> s[i];
        i++;
    }

    cout << "请输入目标字符串:";
    cin >> p;
    //在字符串库中寻找目标字符串
    int j = 0;
    while(i--)
    {
        n++;
        if( Search(s[j++], p) )
        {
            cout <<"\n在库中的第" << n << "个位置";
            num++;
        }
    }
    if( !num )
        cout << "库中不存在"<< "\n";
    else
        cout << "\n\n库中一共有" << num << "个目标字符串";

    return 0;
}

方法二思路分析:利用素数对应表,将每个字母对应相应的素数,然后求解各字符串对应的素数乘积,最终比较两个素数乘积是否相等[是则为兄弟字符串,否则不是]。【程序实现这里不再赘述,和“字母串的包含”专题中的‘素数相乘法’类似】

1.3字符串的全排序

全排列的递归实现参考文档:

https://blog.csdn.net/lemon_tree12138/article/details/50986990 

https://blog.csdn.net/dreamzuora/article/details/52768439 

https://blog.csdn.net/morewindows/article/details/7370155

July著《编程之法》-字符串_第2张图片

想要上图PDF版本以及更多总结,在这篇博客留下您的邮箱https://blog.csdn.net/shiyideliutang/article/details/100086498,第一时间为您发送。

/**< 递归实现全排列 */
#include
using namespace std;
#include 

void CalcAllPermutation(char *a, int from, int to)
{
    if( to <= 1)
        return;

    if(from == to)//递归结束条件
    {
        for(int i = 0; i <= to; i++)
            cout << a[i];

        cout << "\n";
    }
    else
    {
        for(int j = from; j <= to; j++)
        {
            //交换两个变量
            swap(a[j], a[from]);//swap()函数为STL库的函数,声明为swap(ElemType &a, ElemType &b)引用传递
            CalcAllPermutation(a, from+1, to);
            swap(a[j], a[from]);
        }
    }
}


int main()
{
    string str;
    cout << "请输入一串字符串:";
    cin >> str;
    //原始打印字符串
    cout << "字符串的原始打印输出为:" << str << "\n";

    //输出原始字符串的全排列
    cout << "-------输出原始字符串的全排列-------\n";
    char *data;
    int len = str.length(), n;
    //开辟足够大的空间来存储
    data = new char[len*2];//在C语言中为:data = (char *)malloc((len * 2)*sizeof(char));
    n = str.copy(data, len, 0);//返回真实复制的字符数量
    if(n == len)//检验一下
    {
        data[len] = '\0';
        CalcAllPermutation(data, 0, len-1);//因为这里string类型无法直接传递给char *类型,所以前面需要先转化一下。
    }

    return 0;
}

July著《编程之法》-字符串_第3张图片

//直接利用STL中的库函数next_permutation来做,库函数对于有重复字符出现时也适用
#include
#include
#include
using namespace std;

char str[1000];
int main()
{
    cout << "Please input astring:";
    cin>>str;

    sort(str,str+strlen(str));//先排序
    //从stl库中调用全排列的库函数
    do
    {
         for(int i=0;i

课后举一反三暂时未做

1.4字符串转化为整数

July著《编程之法》-字符串_第4张图片

//自己做的答案
#include 
using namespace std;
#include
#include 

double StrToInt(const char *str)
{
    double sum = 0, sum1 = 0;
    int len = strlen(str);//字符串的实际长度
    for(int i = len-1; i >=0; i--)
    {
    //由于pow函数声明为“ double pow(double x, double y);”所以定义sum务必注意,定义为int会出错。
       sum = sum + (*str - '0') * pow(10,i);
       str++;
    }

    return sum;
}

int main()
{
    char str[100];
    cin >> str;
    double sum = StrToInt(str);

    cout.setf(ios_base::floatfield, ios_base::fixed);//定点数显示
    cout.precision(1);//因为上一条语句设置为定点数显示,所以这里精度为小数点后的位数。
    cout << "转化为整数是:" << sum << endl;

    return 0;
}

坑位1-pow()函数

 pow函数原型为: double pow(double x, double y);所以在存储其结果时候需要谨慎一点最好声明为double类型,否则有时候会无端端的出错。

//考虑较为全面的思路,除了溢出条件未考虑
#include
using namespace std;
#include 
#include 

int StrToInt(const char*str)
{
	int n = 0;
	//判断输入是否为空
	if (str == 0)
		return 0;
	//处理空格
	while (isspace(*str))
		str++;
	//处理正负
	int sign = 1;
	if (*str == '-')
	{
		sign = -1;
		str++;
	}
	//正式处理转化
	while (isdigit(*str))
	{
		int c = *str - '0';
		n = n * 10 + c;
		str++;
	}

	return sign>0? n:-n;
}

int main()
{
	string str;
	const char* str1;
	cout << "请输入一串数字串:";
	cin >> str;

	str1 = str.data();//因为函数的参数为char*类型,所以需要提前转化一下。
	int sum = StrToInt(str1);
	cout << "最终转化的数字为" << sum << "\n\n";

	system("pause");
	return 0;
}

1.5回文判断

回文正着看和反着看都一样。

//从两边往中间扫描遍历,进行比较
#include 
using namespace std;
#include
//判断输入输入的字符串是否为回文系列
bool is_HuiWen(char *str)
{
	int len = strlen(str);//字符串的实际长度
	char *head = str;//头指针
	char *tool = str + len-1;//尾指针[注意这里需要减去1]
	//判断意外输入的情况
	if(str == NULL)
		return false;
	//从两边到中间判断
	while (head <= tool)
	{
		if (*head != *tool)
			return false;

		head++;
		tool--;
	}
	return true;
}

int main()
{
	string str;
	cout << "请输入一串字符串:";
	cin >> str;
	//将string类型转化为char*类型
	int len = str.length();
	char *data;
	data = new char[2*len];
	str.copy(data, len, 0);
	data[len] = '\0';
	//判断是否为回文序列
	if (is_HuiWen(data))
		cout << str << "是回文序列" << '\n';
	else
		cout << str << "不是回文序列" << '\n';

	return 0;
}
//从中间往两边扫描遍历,进行比较
#include 
using namespace std;
#include
//判断输入输入的字符串是否为回文系列
bool is_HuiWen(char *str)
{
	int len = strlen(str);//字符串的实际长度
	int n = ((len>>1) - 1) >= 0?  ((len>>1) - 1):0;//注意右移运算的优先级低于算术运算符
	char *left = str + n;//左指针
	char *right = str + len-1 - n;//右指针
	//判断意外输入的情况
	if(str == NULL)
		return false;
	//从中间到两边判断
	while ( left >= str)
	{
		if (*left != *right)
			return false;

		right++;
		left--;
	}
	return true;
}

int main()
{
	string str;
	cout << "请输入一串字符串:";
	cin >> str;
	//将string类型转化为char*类型
	int len = str.length();
	char *data;
	data = new char[2*len];
	str.copy(data, len, 0);
	data[len] = '\0';
	//判断是否为回文序列
	if (is_HuiWen(data))
		cout << str << "是回文序列" << '\n';
	else
		cout << str << "不是回文序列" << '\n';

	return 0;
}

举一反三之链表回文

July著《编程之法》-字符串_第5张图片

预备知识:单链表的逆置【辅助指针法、递归法】

参考文档:https://blog.csdn.net/heyabo/article/details/7610732

/*******辅助指针、递归方法实现单链表的逆置*********/
#include
using namespace std;

typedef char ElemType;
typedef int Status;
#define OK 1
#define ERROR 0
//定义链表的存储结构
typedef struct Node
{
	ElemType data;
	struct Node* next;
}Node, *LinkList;
//初始化单链表
Status InitList(LinkList *L)
{
	*L = new Node;
	if(*L == NULL)
		return ERROR;

	(*L)->next = NULL;
	return OK;
}
//求解单链表中的数据长度
int Length(LinkList L)
{
	int i = 0;
	LinkList p = L->next;//指向第一个结点
	while(p)
	{
		i++;
		p = p->next;
	}
	return i;
}
//打印输出有头结点的单链表
void print(LinkList L)
{
	LinkList p = L->next;//指向第一个结点
	while(p)
	{
		cout << p->data << " ";
		p = p->next;
	}
	cout << '\n';
}
//打印输出无头结点的单链表
void print2(LinkList L)
{
	LinkList p = L;//指向第一个结点
	while(p)
	{
		cout << p->data << " ";
		p = p->next;
	}
	cout << '\n';
}
//初始化创建单链表
void CreatList(LinkList *L, int n)
{
	LinkList p,r;
	*L = new Node;
	r = *L;

	cout << "请输入单链表的数据元素:";
	for(int i =0; i < n; i++)
	{
		  p = new Node;
		  cin >> p->data;
		  r->next = p;
		  r = p;
	}
	r->next = NULL;
}
//逆置单链表[利用辅助指针的方法]
void Reverse(LinkList *L)
{
	  cout << "将单链表逆置ing!!!" << "\n";
	  if((*L) == NULL || (*L)->next == NULL)//判断链表是否为空表
			return;
	  LinkList pPre = NULL;//先前指针
	  LinkList pCur = (*L)->next;//当前指针
	  LinkList pNext = NULL;//后继指针
	  while(pCur != NULL)
	  {
			pNext = pCur->next;
			pCur->next = pPre;
			//重现定义指针类型[下面两句顺序不可以颠倒]
			pPre = pCur;
			pCur= pNext;
	  }
	  (*L)->next = NULL;//头结点作为了最后一个结点,指向NULL
	  //记录新的头结点
	  *L = pPre;
}
//逆置单链表[利用递归的方法]
void Reverse2(LinkList *L, LinkList pCur)
{
	  if(pCur == NULL || pCur->next == NULL)
			*L = pCur;
	  else
	  {
			LinkList pNext = pCur->next;
			Reverse2(L, pNext);
			pNext->next = pCur;
			pCur->next = NULL;
	  }
}

int main()
{
	  LinkList L;
	  InitList(&L);//初始化单链表
	  int n;
	  cout << "请输入单链表的长度:";
	  cin >> n;
	  CreatList(&L,n);//创建单链表
	  int len = Length(L);
	  cout << "单链表的长度为" << len << "\n";
	  cout << "原始打印输出的单链表为:";
	  print(L);//打印输出单链表

	  //逆置单链表[辅助指针法]
	  Reverse(&L);
	  cout << "单链表逆置[辅助指针法]后打印输出为:";
	  print2(L);//打印输出单链表[这里单链表不存在头结点]
	  
	  //逆置单链表[递归法]
	  Reverse2(&L, L);
	  cout << "单链表逆置[递归法]后打印输出为:";
	  print2(L);//打印输出单链表[这里单链表不存在头结点]
	  return 0;
}

举一反三之栈回文

July著《编程之法》-字符串_第6张图片

1.6最长回文子串

/*********自做答案*********/
#include 
using namespace std;
#include 

//【中心扩展法】寻找最长回文子串
void Search(const char *str, int *num)
{
    int len = strlen(str);
    if(len == 1)
        return;
    else if(len == 2)
    {
        if(*str == *(str+1))
            *num = 2;
    }
    else
    {
        const char *p = str+1;
        char const *temp1,*temp2;//char const和const char无区别
        int num_temp = *num;
        while(p < str+len)
        {
            //针对回文子串为奇数个的情况
            temp1 = temp2 = p;
            while(temp1 > str && temp2 < str+len)
            {
                temp1--;
                temp2++;
                if(*temp1 == *temp2)
                    num_temp++;
                else
                    break;
            }
            if(num_temp > *num)
            {
                *num = num_temp*2 + 1;
                num_temp = 0;
            }

            //针对回文子串为偶数个的情况
            temp1 = p;
            temp2 = p+1;
            while(temp1 >= str && temp2 <= str+len)
            {
                if(*temp1 == *temp2)
                    num_temp++;
                else
                    break;
                temp1--;
                temp2++;
            }
            if(num_temp > *num)
            {
                *num = num_temp*2;
                num_temp = 0;
            }
            p++;
        }
    }
}


int main()
{
    string str;
    int num = 0;//存储最长回文子串的长度
    cout << "请输入一串字符串:";
    cin >> str;

    Search(str.data(), &num);//string类型转换
    if(!num)
        cout << "不存在回文串";
    else
        cout << "最长回文子串的长度为:" << num << endl;

    return 0;
}

 const在指针中的运用

July著《编程之法》-字符串_第7张图片

/*********参考答案*********/
#include 
using namespace std;
#include 

//【中心扩展法】寻找最长回文子串
void Search(const char *str, int *num)
{
    int len = strlen(str);
    int num_temp = 0;
    //回文中心从0依次遍历到len
    for(int i = 0; i <= len; i++)
    {
        //回文长度为奇数
        for(int j = 0; (i-j)>=0 && (i+j) <= len; j++)
        {
            if(str[i-j] != str[i+j])
                break;
            num_temp = 2*j + 1;
        }
        if(num_temp > *num)
            *num = num_temp;

        //回文长度为偶数
        for(int k = 0; (i-k)>=0 && (i+k+1) <= len; k++)
        {
            if(str[i-k] != str[i+k+1])
                break;
            num_temp = 2*k + 2;
        }
        if(num_temp > *num)
            *num = num_temp;
    }
}

int main()
{
    string str;
    int num = 0;//存储最长回文子串的长度
    cout << "请输入一串字符串:";
    cin >> str;

    Search(str.data(), &num);//string类型转换
    if(!num)
        cout << "不存在回文串";
    else
        cout << "最长回文子串的长度为:" << num << endl;

    return 0;
}

“马拉车”算法实现

https://blog.csdn.net/weixin_42373330/article/details/82118694

#include//使用C语言中的函数:scanf,printf
#include
#include
#include 
#include 
using namespace std;
#define ll long long
char str[2010];
int p[2500];
int main()
{
	while(scanf("%s",str)==1)//字符数组的输入也可以像string类型那样整体输入
                             //当str定义为string类型时候,可以使用:cin >> str输入,但是又不方便单个元素的取用
                             //这里这种方法既可以保证输入时候像string类型方便,也可保证使用时像char数组类型方便
    {
        int len=strlen(str);
        memset(p,0,sizeof(p));
        //预处理
        for(int i=len;i>=0;i--)
        {
            str[2*i+2]=str[i];
            str[2*i+1]='#';
        }
        str[0]='$';
        //初始化“马拉车算法”的一些定义量
        int mx=0;
        int id=0;
        int res=0;
        for(int i=0;i<=2*len+1;i++)
        {
            if(mx>i)
                p[i]=min(p[2*id-i],mx-i);
            else
                p[i]=1;

            while(str[i-p[i]]==str[i+p[i]])
                p[i]++;

            if(i+p[i]>mx)
            {
                mx=i+p[i];
                id=i;
            }
        }

        //输出P数组
        for(int i=0;i<=2*len+1;i++)
            printf("%d ",p[i]);
        printf("\n");

    }
	return 0;

}

 

 

 

 

 

 

 

 

 

 

 

 

你可能感兴趣的:(备战offer)