牛客网刷题

1.A+B 大数相除

本题要求计算A/B,其中A是不超过1000位的正整数,B是1位正整数。你需要输出商数Q和余数R,使得A = B * Q + R成立。

输入格式:

输入在1行中依次给出A和B,中间以1空格分隔。

输出格式:

在1行中依次输出Q和R,中间以1空格分隔。

输入样例:
123456789050987654321 7
输出样例:
17636684150141093474 3

/* 
http://pat.zju.edu.cn/contests/pat-b-practise/1017 A除以B (20)  //用字符串来处理
*/  
#include  
#include  
using namespace std;  
  
int main()  
{  
    string A,Q;  
    int B,R=0;  
    cin>>A>>B;  
    int length = A.length();  
    int temp = A[0]-'0';  
    if(temp>=B)  
        Q.push_back(temp/B+'0');     //避免首位出现‘0’
    for(int i =1;i

2.打印素数

令Pi表示第i个素数。现任给两个正整数M <= N <= 10000,请输出PM到PN的所有素数。

#include
#include
int main()
{
  using namespace std;
  int m,n,count = 0;
  cin >> m >> n;
  for (int i = 2;count <= n;i++)
  {
    int temp = 0;
    for (int j = 2;j <= sqrt(i);j++)   //只需到根号就行
      if (i % j == 0)
        ++temp;      //这里可优化,找到即退出
    if (temp == 0)
      ++count;      //count代表第几个素数
    if (count >= m && count <= n && temp == 0)
    {
      cout << i;
      if ((count - m) % 10 == 9)
        cout << endl;
      else if (count != n)
        cout << " ";
    }
  }
  cout << endl;
  return 0;
}                          

3.德才排序

链接:https://www.nowcoder.com/questionTerminal/97b6a49a85944650b2e3d0660b91c324
来源:牛客网

输入描述:
输入第1行给出3个正整数,分别为:N(<=105),即考生总数;L(>=60),为录取最低分数线,即德分和才分均不低于L的考生才有资格

被考虑录取;H(<100),为优先录取线——德分和才分均不低于此线的被定义为“才德全尽”,此类考生按德才总分从高到低排序;才分不到

但德分到线的一类考生属于“德胜才”,也按总分排序,但排在第一类考生之后;德才分均低于H,但是德分不低于才分的考生属于“才德兼

亡”但尚有“德胜才”者,按总分排序,但排在第二类考生之后;其他达到最低线L的考生也按总分排序,但排在第三类考生之后。


随后N行,每行给出一位考生的信息,包括:准考证号、德分、才分,其中准考证号为8位整数,德才分为区间[0, 100]内的整数。数字间以空格分隔。


输出描述:
输出第1行首先给出达到最低分数线的考生人数M,随后M行,每行按照输入格式输出一位考生的信息,考生按输入中说明的规则从高到低排序。当某类考生中有多人

总分相同时,按其德分降序排列;若德分也并列,则按准考证号的升序输出。

总体思路:
先分类再排序,可借助STL中的set组件统一进行
  1. 建立结构体。    除了考号、德分、才分,再添加总分sum、等级level,方便排序
  2. 自定义结构体的排序函数。      先按等级排,再按总分、德分、考号排
  3. 分类。      对读入的考生分类,设定其level值,并插入set中
  4. 输出。       set可根据自定义的排序函数自动排序,直接反序输出即可

链接:https://www.nowcoder.com/questionTerminal/97b6a49a85944650b2e3d0660b91c324
来源:牛客网

#include 
#include 
 
using namespace std;
 
class Student
{
public:
    int id, morality, ability, sum, level;
    Student(int id, int morality, int ability) {
        this->id = id;
        this->morality = morality;
        this->ability = ability;
        this->sum = morality + ability;
        level = 4;//默认为第4等级,可改
    }
    bool operator <(const Student& another)const {    //set容器多级排序,等级4到1(差到好)
        if(level != another.level) {
            return level>another.level;
        } else if(sum != another.sum) {
            return another.sum>sum;
        } else if(morality != another.morality) {
            return another.morality>morality;
        } else {
            return id>another.id;
        }
    }
};
 
int main()
{
    // 基本变量
    int N, L, H;
    cin >> N >> L >> H;
    set student;
 
    // 分类划级
    for(int i=0; i> id >> morality >> ability;
        Student stu(id, morality, ability);
        if(stu.morality= H && stu.ability >= H) {
            stu.level = 1;
        } else if(stu.morality >= H) {
            stu.level = 2;
        } else if(morality>=ability) {
            stu.level = 3;
        } else {
            stu.level = 4;
        }
        student.insert(stu);      //set容器
    }
 
    // 输出结果
    set::reverse_iterator iter;
    cout << student.size() << endl;
    for(iter=student.rbegin(); iter != student.rend(); iter++) {
        cout << (*iter).id << " " << (*iter).morality << " " << (*iter).ability << endl;
    }
    return 0;
}

4.月饼最大售价(贪心)

链接:https://www.nowcoder.com/questionTerminal/6fc9a928c7654b0fbc37d16b8bd29ff9
来源:牛客网

每个输入包含1个测试用例。每个测试用例先给出一个不超过1000的正整数N表示月饼的种类数、以及不超过500(以万吨为单位)的正整数

D表示市场最大需求量。随后一行给出N个正数表示每种月饼的库存量(以万吨为单位);最后一行给出N个正数表示每种月饼的总售价(以亿

元为单位)。数字间以空格分隔。

#include 
#include 
#include 
using namespace std;
struct yuebing{
double kucun;
double shoujia;
double danjia;
};
bool comparison(yuebing a,yuebing b)
{
return a.danjia>b.danjia;
}
int main()
{
double sum = 0;
int N,D;
cin>>N>>D;
vector yue(N);
for(int i =0;i<2*N;i++){
if(i<=N-1)
cin>>yue[i].kucun;
else
cin>>yue[i-N].shoujia;
}
for(int i=0;i


5.快速排序

快速排序的时间复杂度为  n*logn,好于冒泡排序,用到分治的思想。一个博客:https://blog.csdn.net/morewindows/article/details/6684558

对挖坑填数进行总结

1.i =L; j = R; 将基准数挖出形成第一个坑a[i]。

2.j--由后向前找比它小的数,找到后挖出此数填前一个坑a[i]中。

3.i++由前向后找比它大的数,找到后也挖出此数填到前一个坑a[j]中。

4.再重复执行2,3二步,直到i==j,将基准数填入a[i]中。

5.排完后左边的数比中间小,右边的数比中间大,再对左右分别递归,直到当前调整区长度不超过1


int partition(int a[], int left, int right) {
    int temp = a[left]; //将最左存入临时变量,左边目前为空值
	while (left < right) {
	    while(left < right && a[right] > temp) right--; //左移
		a[left] = a[right]; //出现右边小于临界的情况,将右边的移到左边,右边目前为空值
		while(left < right && a[left] <= temp) left++;
		a[right] = a[left];   //出现左边大于临界的情况,将左边的移到右边,左边目前为空值
	}
	a[left] = temp; // temp放到left与right相遇处
	return left;
}

//快速排序
void quicksort(int a[],int left,int right) {
    if(left < right) {   //当前区间长度不小于1
	    //将【left,right】按a【left】一分为二
		int pos = partition(a,left,right);
		quicksort(a,left,pos-1);   //左子区间快排
		quicksort(a,pos+1,right);  //右子区间快排
	}
}

6.深度优先(DFS)本质是栈

如背包问题:

牛客网刷题_第1张图片

牛客网刷题_第2张图片


7.广度优先(BFS)实质是队列

牛客网刷题_第3张图片

 #include 
 #include 
 #include 
 using namespace std;
 const int maxn = 100;
 struct node {
 	int x,y;   //位置 
 	int step;  //step为起点到达该位置的最少步数,即层数 
 }S,T,Node;  //起点,终点,临时结点 
 
 int n,m;   //行列 
 char maze[maxn][maxn];   //迷宫信息 
 bool inq[maxn][maxn] = {false};  //记录是否入列过 
 int X[4] = {0,0,1,-1};  //上下左右 
 int Y[4] = {1,-1,0,0};
 
 //检测该位置是否有效 
 bool test(int x, int y) {
 	if (x >= n || x<0 || y>=m || y<0) return false;
	if (maze[x][y] == '*') return false;
	if (inq[x][y] == true) return false;
	return true;
 }
 
 int BFS() {
 	queue q;  //定义队列 
 	q.push(S);      //起点入队 
 	while(!q.empty()) {
 		node top = q.front();   //取首元素 
 		q.pop();
 		if(top.x == T.x && top.y == T.y) {   //到达终点,返回步数 
 			return top.step;
		}
		for(int i = 0; i< 4;i++) {  //循环4次,得到四个相邻位置 
			int newX = top.x + X[i];
			int newY = top.y + Y[i];
			if(test(newX,newY)) {   //位置有效 
				Node.x = newX,Node.y = newY;
				Node.step = top.step + 1;
				q.push(Node);      //加入队列 
				inq[newX][newY] = true; //已入队 
		    }
	    }
	 }
	 return -1;  //无法到达终点 
 }
 
 int main() {
 	scanf("%d%d",&n,&m);
 	for(int i = 0; i < n; i++) {
 		getchar();  //过滤换行符 
 		for(int j = 0; j < m; j++) {
 			maze[i][j] = getchar();
		 }
		 maze[i][m+1] = '\0';
	 }
	 scanf("%d%d%d%d",&S.x,&S.y,&T.x,&T.y);  //起点,终点坐标 
	 S.step = 0;  //初始层数为0 
	 printf("%d\n",BFS());
	 return 0;
 }

牛客网刷题_第4张图片


8.BST二叉树的建立

牛客网刷题_第5张图片

牛客网刷题_第6张图片

 //先输入整个二叉树的形状,在输入一列数(不要求顺序) 
#include 
#include 
#include 
using namespace std;
const int maxn = 110;
 
struct node {     //静态二叉树 
    int data;
 	int lchild, rchild;
} Node[maxn];
 
int n, in[maxn], num = 0; //n为结点数,in为中序序列,num为已经输入/输出的个数 

void inOrder(int root) {  //中序遍历,将排序号的序列填入二叉树系欸按 
	if(root == -1) {
		return;
	}
	inOrder(Node[root].lchild);
	Node[root].data = in[num++];
	inOrder(Node[root].rchild);
}

void BFS(int root) {   //层序遍历 
	queue q;  //队列存地址 
	q.push(root);
	num = 0;
	while(!q.empty()) {
		int now = q.front();
		q.pop();
		printf("%d",Node[now].data);
		num++;
		if(num < n)  printf(" ");
		if(Node[now].lchild != -1) q.push(Node[now].lchild);  //左子树非空 
		if(Node[now].rchild != -1) q.push(Node[now].rchild);
	}
}

int main() {
	int lchild,rchild;
	scanf("%d",&n);
	for(int i = 0; i < n; i++) {
		scanf("%d%d",&lchild,&rchild);    // 左右孩子编号 
		Node[i].lchild = lchild;
		Node[i].rchild = rchild;
	}
	for(int i = 0; i < n; i++) {
		scanf("%d",&in[i]);
	}
	sort(in,in+n);  //从小到大排,作为中序输入 
	inOrder(0);  //输入数 
	BFS(0);   //层序打印 
	return 0;
}

9.图的最短路径(Dijkstra),时间复杂度n*n,动态规划,单源,权值非负

 #include 
 #include 
 using namespace std;
 const int MAXV = 1000;  //最大顶点数 
 const int INF = 1000000;  //初始边权很大 
 
 int n,m,s,G[MAXV][MAXV];
 int d[MAXV];   //起点到达个点的最短路径 
 bool vis[MAXV] = {false};  //标记是否访问过 
 
 void  Dijkstra(int s) {
 	fill(d,d+MAXV,INF); //全设置为inf 
 	d[s] = 0; //到到起点自身最短距离为0 
 	for(int i = 0; i < n; i++) {  //循环n次 
 		int u = -1,min = INF;   //u使d【u】最小,min存放最小的的d【u】 
 		for(int j = 0; j < n; j++) {  //找到未访问的顶点中d【】最小的 
 			if(vis[j] == false && d[j] < min) {
 				u = j;
 				min = d[j];
			 }
		 }
		 
		 if(u == -1) return;   //说明剩下的点都与起点不同 
		 vis[u] = true;  //标记u已经访问 
		 for(int v = 0;v < n; v++) {    //如果v未访问,u到v能访问,且有优化空间 
		 	if(vis[v] == false && G[u][v] != INF && d[u]+G[u][v] < d[v]) {
		 		d[v] = d[u] + G[u][v];
			 }
		 }
	 }
 }
 
 int main() {
 	int u,v,w;
 	scanf("%d%d%d",&n,&m,&s); //顶点个数,边数,起点 
 	fill(G[0],G[0] + MAXV*MAXV,INF);  //初始化图 
 	for(int i = 0; i < m; i++) {
 		scanf("%d%d%d",&u,&v,&w);  //输入u,v,及权值 
 		G[u][v] = w;
	 }
	 Dijkstra(s);
	 for(int i = 0;i < n; i++) {
	 	printf("%d",d[i]);
	 }
	 return 0;
 }

核心思想:默认其余点与起点距离无限大

1.先找到离起点最近的点,访问了,访问后更新起点到剩余点的路径,看有没有更近的可能(inf->某个值)

2.在剩下的点中找最近的点,不断重复1,2


加强:打印经过结点,注意到每一次更新最短路径即意味着前驱点为当前节点,递归即可

 #include 
 #include 
 using namespace std;
 const int MAXV = 1000;  //最大顶点数 
 const int INF = 1000000;  //初始边权很大 
 
 int n,m,s,G[MAXV][MAXV];
 int d[MAXV];   //起点到达个点的最短路径 
 int pre[MAXV];   // 记录前驱点 
 bool vis[MAXV] = {false};  //标记是否访问过 
 
 void  Dijkstra(int s) {
 	fill(d,d+MAXV,INF); //全设置为inf 
 	for(int i = 0; i < n; i++) pre[i] = i;   //前驱点为本身 
 	d[s] = 0; //到到起点自身最短距离为0 
 	for(int i = 0; i < n; i++) {  //循环n次 
 		int u = -1,min = INF;   //u使d【u】最小,min存放最小的的d【u】 
 		for(int j = 0; j < n; j++) {  //找到未访问的顶点中d【】最小的 
 			if(vis[j] == false && d[j] < min) {
 				u = j;
 				min = d[j];
			 }
		 }
		 
		 if(u == -1) return;   //说明剩下的点都与起点不同 
		 vis[u] = true;  //标记u已经访问 
		 for(int v = 0;v < n; v++) {    //如果v未访问,u到v能访问,且有优化空间 
		 	if(vis[v] == false && G[u][v] != INF && d[u]+G[u][v] < d[v]) {
		 		d[v] = d[u] + G[u][v];
		 		pre[v] = u;   //到v的最短路径前驱点为u 
			 }
		 }
	 }
 }
 
 void  DFS(int s, int v) {
 	if(v==s){
 		printf("%d\n",s);
 		return;
	 }
	 DFS(s,pre[v]);
	 printf("%d\n",v);
 } 
 int main() {
 	int u,v,w;
 	scanf("%d%d%d",&n,&m,&s); //顶点个数,边数,起点 
 	fill(G[0],G[0] + MAXV*MAXV,INF);  //初始化图 
 	for(int i = 0; i < m; i++) {
 		scanf("%d%d%d",&u,&v,&w);  //输入u,v,及权值 
 		G[u][v] = w;
	 }
	 Dijkstra(s);
	 for(int i = 0;i < n; i++) {
	 	printf("%d",d[i]);
	 }
	 DFS(0,5);
	 return 0;
 }

10.Flyod,多源最短路径,n*n*n

 #include 
 #include 
 using namespace std;
 const int INF = 100000;
 const int MAXV  = 200;  //最大定点数,时间复杂度n3次 
 int n, m; 
 int dis[MAXV][MAXV];
 
 void Floyd() {
 	for (int k = 0; k < n; k++) {  //k,做中节点,放在最外,防止后面更新时前面已经访问的点无法更新 
 		for (int i = 0; i < n; i++) {
 			for (int j = 0; j < n; j++) {
 				if(dis[i][j]!= INF && dis[k][j] != INF && 
				   dis[i][k] + dis[k][j] < dis[i][j]) {
				   	dis[i][j] = dis[i][k] + dis[k][j];   //找到最短路径 
				}
			 }
		 }
	 }
 }
 
 int main() {
 	int u,v,w;
 	fill(dis[0],dis[0]+MAXV*MAXV,INF);
 	scanf("%d%d",&n,&m);  //顶点数,边数 
 	for(int i = 0; i < n; i++) {
 		dis[i][i] = 0;
	 }
	 for(int i = 0; i < m; i++) {
	 	scanf("%d%d%d",&u,&v,&w);  //有向图输入 
	 	dis[u][v] = w;
	 }
	 Floyd();
	 for(int i = 0; i < n; i++) {
	 	for(int j = 0; j < n; j++) {
	 		printf("%d ",dis[i][j]);
		 }
		 printf("\n");
	 }
	 return 0;
	 
 }


11.最小生成树,prim算法

 #include 
 #include 
 using namespace std;
 const int MAXV = 1000;  //最大顶点数 
 const int INF = 1000000;  //初始边权很大 
 
 int n,m,s,G[MAXV][MAXV];
 int d[MAXV];   //起点到达个点的最短路径 
//int pre[MAXV];   // 记录前驱点 
 bool vis[MAXV] = {false};  //标记是否访问过 
 
 int  prim() {
 	fill(d,d+MAXV,INF); //全设置为inf 
 	//for(int i = 0; i < n; i++) pre[i] = i;   //前驱点为本身 
 	d[0] = 0; //到已访问集合最短距离为0 
 	int ans = 0;
 	for(int i = 0; i < n; i++) {  //循环n次 
 		int u = -1,min = INF;   //u使d【u】最小,min存放最小的的d【u】 
 		for(int j = 0; j < n; j++) {  //找到到已访问集合最短距离的点,d【u】为最短距离 
 			if(vis[j] == false && d[j] < min) {
 				u = j;
 				min = d[j];
			 }
		 }
		 
		 if(u == -1) return -1;   //说明剩下的点都与起点不通 
		 vis[u] = true;  //标记u已经访问 
		 ans += d[u]; 
		 for(int v = 0;v < n; v++) {    //如果v未访问,u到v能访问,且已访问集合最短距离有优化空间 
		 	if(vis[v] == false && G[u][v] != INF && G[u][v] < d[v]) {
		 		d[v] =  G[u][v];
		 	//pre[v] = u;   //到v的最短路径前驱点为u 
			 }
		 }
	 }
	 return ans;
 }
 
 
 int main() {
 	int u,v,w;
 	scanf("%d%d",&n,&m); //顶点个数,边数 
 	fill(G[0],G[0] + MAXV*MAXV,INF);  //初始化图 
 	for(int i = 0; i < m; i++) {
 		scanf("%d%d%d",&u,&v,&w);  //输入u,v,及权值 
 		G[u][v] = G[v][u]  = w;
	 }
	 int ans = prim();
	 printf("%d\n",ans);
	 
	 return 0;
 }

dijkstra 算法十分相似,不同之处在于  d[i]存储的是到 点i到 已访问集合 的最短距离

总体思路:找到距离以访问集合最短的点,访问,并累计距离

             形成新的以访问集合,遍历看有没有未访问点到集合的最短距离更新

              寻找下一个最短点,重复。


12.动态规划DP

问题拥有最优子结构,必须有重叠子结构。

动态与分治:动态子问题重叠,是最优解。分治子问题不重叠,不一定是最优解。

动态与贪心:贪心只考虑当前,不一定最优。动态考虑全局,最优。


最大连续子序列和,时间复杂度n

,dp[i]表示以第i个元素为结尾的最大连续子序列和,最后max{dp[i]}就是答案

#include 
#include 
using namespace std;

const int maxn = 100;
int A[maxn],dp[maxn]; //A为原始序列,dp村以i为尾的最长子序列和 

int main() {
	int n;
	scanf("%d",&n);
	for (int i = 0; i < n; i++) {
		scanf("%d",&A[i]);
	}
	
	dp[0] = A[0];
	for (int i = 0; i < n; i++) {
		dp[i] = max(A[i],dp[i-1]+A[i]); //状态转换方程 
	}
	int k = 0;
	for (int i = 0;i < n; i++) {
		if(dp[i] > dp[k]) {
			k = i;
		}
	}
	printf("%d\n",dp[k]);
	return 0; 
} 


13.背包

01背包:一件物品只有一个,时间复杂度O(NV)

牛客网刷题_第7张图片

#include 
#include 
using namespace std;

const int maxn = 100;  //物品最大件数 
const int maxv = 1000;  //背包V的上限 
int w[maxn],c[maxn],dp[maxn][maxv];

int main() {
	int n,V;
	scanf("%d%d",&n,&V);
	for(int i = 0;i < n; i++) {
		scanf("%d",&w[i]); //物品空间 
	}
	
	for(int i = 0;i < n; i++) {
		scanf("%d",&c[i]); //物品价值 
	}

	
	for(int i = 0; i < n; i++) {
		dp[i][0] = 0;  //边界条件,容量为0时最大值为0 
	}
	for(int v = 1; v <= V; v++) {
	
     dp[0][v]=(v < w[0])?0:c[0];  //考虑第一件物品 
    }
	for(int i = 1; i < n; i++) {  // 状态转移方程 
		for(int v = 1; v <= V; v++) {
			if (v >= w[i]) {
			
			dp[i][v] = max(dp[i-1][v],dp[i-1][v-w[i]]+c[i]); // 状态转移方程 

		    } else {
		    	dp[i][v] = dp[i-1][v]; 
			} 
		}
	}
  
	printf("%d\n",dp[n-1][V]);
	return 0;
}

完全背包问题:每个物品无限多,只需改变两处



#include 
#include 
using namespace std;

const int maxn = 100;  //物品最大件数 
const int maxv = 1000;  //背包V的上限 
int w[maxn],c[maxn],dp[maxn][maxv];

int main() {
	int n,V;
	scanf("%d%d",&n,&V);
	for(int i = 0;i < n; i++) {
		scanf("%d",&w[i]); //物品空间 
	}
	
	for(int i = 0;i < n; i++) {
		scanf("%d",&c[i]); //物品价值 
	}

	
	for(int i = 0; i < n; i++) {
		dp[i][0] = 0;  //边界条件,容量为0时最大值为0 
	}
	for(int v = 1; v <= V; v++) {
	
     dp[0][v]=(v < w[0])?0:(v/w[0])*c[0];  //考虑第一件物品 
    }
	for(int i = 1; i < n; i++) {  // 状态转移方程 
		for(int v = 1; v <= V; v++) {
			if (v >= w[i]) {
			
			dp[i][v] = max(dp[i-1][v],dp[i][v-w[i]]+c[i]);
		    } else {
		    	dp[i][v] = dp[i-1][v]; 
			} 
		}
	}
  
	printf("%d\n",dp[n-1][V]);
	return 0;
}

多重背包问题:每件物品有固定个数,可以将每一类物品的每一件重新分类,转化为01背包问题


14.求两个字符串中连续最长子序列的长度

用hash进行比较


前i个字符的hash

牛客网刷题_第8张图片

任意i,j区间字符的hash

#include 
#include 
#include 
#include 
#include 
#include 
//不知道什么原因,运行失败
using namespace std;
typedef long long LL;
const LL mod = 1000000007; //mod为计算hash的模数 
const LL p = 10000019; //p为进制数 
const LL maxn = 1000;  //字符串最长长度 
//powp[i] = p*i%mod,h1存放str1的hash 
LL powp[maxn],h1[maxn] = {0},h2[maxn] = {0};

//pr1存放str1所有<子串的hash,子串长度 >
vector> pr1,pr2;  

//初始化powp函数,进制转化 
void init(int len) {
	powp[0] = 1;
	for(int i = 1; i <= len; i++) {
		powp[i] = (powp[i-1]*p)% mod; 
	}
}

//计算str的hash 
void calh(LL h[],string &str) {
	h[0] = str[0];
	for(int i = 1; i < str.length(); i++) {
		h[i] = (h[i-1]*p+str[i]) % mod;
	} 
}

//计算h[i...j]的hash 
int calsinglesubh(LL h[],int i,int j) {
	if(i == 0) return h[j]; //h[0..j]单独处理 
	return  ((h[j] - h[i-1]*powp[j-i+1]) % mod + mod) % mod; 
	 
}

//计算所有子串的hash,并存入pr 
void calsubh(LL h[],int len,vector>&pr) {
	for(int i = 0; i < len; i++) {
		for(int j = i; j < len;j++) {
		int hashvalue = calsinglesubh(h,i,j);
		pr.push_back(make_pair(hashvalue,j-i+1));
	    }
	}
}

//计算pr1和pr2中相同的hash,维护最大长度 
int getmax() {
	int ans = 0;
	for(int i = 0; i < pr1.size();i++) {
		for(int j = 0; j < pr2.size();i++) {   
		    if(pr1[i].first == pr2[j].first) {
		    	ans = max(ans,pr1[i].second);
			}
		}
		
	}
	return ans;
}
int main() {
	string str1,str2;
	getline(cin,str1);
	getline(cin,str2);
	init(max(str1.length(),str2.length())); //初始化powp
	calh(h1,str1);  //计算str1str2的hash 
	calh(h2,str2);
	calsubh(h1,str1.length(),pr1); //计算所有字串的hash 
	calsubh(h2,str2.length(),pr2);
	printf("ans = %d\n",getmax());
	return 0;
}

另一个方法,

牛客网刷题_第9张图片

牛客网刷题_第10张图片

#include 
#define ll long long
#define inf 0x3f3f3f3f
#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;
int m[100][100];
int main(){//freopen("1.txt","r",stdin);
    int i,j,k1,k2,n,ans=0,max;
    string s1,s2;
    getline(cin,s1);
    getline(cin,s2);
    k1=s1.size();
    k2=s2.size();
    mem(m,0);
    for(i=0;ians)ans=max;
        }
    }//统计从左边第一列开始的斜向右下斜线的最大值
    for(i=0;ians)ans=max;
        }
    }//统计从顶部第一行开始的斜向右下斜线的最大值
    printf("%d\n",ans);
    /*
    for(i=0;i

你可能感兴趣的:(牛客网刷题)