zoukankan      html  css  js  c++  java
  • 串和矩阵压缩的小测试

    1. kmp计算一个字符串是由多少个重复的子串构成的

    题目链接

    题意

    计算一个字符串是由多少个重复的子串构成的。比如:"abcd"是由一个abcd组成的,"ababab"是由三个"ab"组成的。

    分析

    既然一个字符串能够被多个相同子串表示,我们可以将这一子串定义为循环节,用ss表示最小的循环节。我们要寻找ss,难道要用枚举不同长度的前缀子串吗?我们观察到,既然这一字符串能被ss表示,那么该字符串的前缀以及后缀的一定长度应该与ss吻合,我们可以联系到(KMP)算法中(Next)数组的计算,而(Next)数组正是为了寻找最长的前缀能够与对应长度的后缀进行匹配。

    由此我们计算出(Next)数组后,定义原字符串长度为len,那么Next[len]​便是最长的循环节的长度,len - Next[len]是最短的循环节长度即ss长度,将这一长度除len,便能知道原字符串有多少个ss表示了。

    #include <string>
    #include <cstdio>
    #include <iostream>
    using namespace std;
    const int MAXN = 1e3;
    string str;
    int mynext[MAXN];
    void BuildNext(){
        int i = 0, comlen = -1;
        mynext[0] = -1;
        int len = str.length();
        while (i <= len){
            if (comlen == -1 || str[i] == str[comlen]){
                i++; comlen++;
                mynext[i] = comlen;
            }
            else
                comlen = mynext[comlen];
        }
    }
    int main(){
        cin >> str;
        BuildNext();
        int len = str.length();
        for (int i = 0; i <= len; i++){
            printf("%d ", mynext[i]);
        }
        printf("%d
    ", len / (len - mynext[len]));
        return 0;
    }
    

    2. 利用三元组完成矩阵加法

    题意

    以三元组表存储的稀疏矩阵AB ,两个矩阵的行数为m,列数为n,非零元个数分别为num1num2。试完成程序,完成A+B。输入会给定行数与列数,非零元的个数,以及每个非零元的行数、列数以及值。

    分析

    本题其实可以用结构体简单模拟一下,又或者是STL的map/set使用,读者可自行尝试。本题题解仅是为了学习三元组矩阵的数据结构。

    我们可以定义一个class,它的成员有:一个记录三元组元素的结构体数组data[]、一个数组专门记录实际矩阵所在行的首个元素rpos[],在对应于结构体数组的下标、三个变量mu,nu,tu分别记录矩阵的行数、列数和非零元个数。

    实际大小为n*n的矩阵,我们从中将非零元特意抽出来,将它们排成一列,即是data[]的用处。那么如何用一数组去表示实际矩阵中的每一行的首个元素?结合tu,在遍历的过程中定义个临时的前缀和数组,去统计从首行到遍历的当前行i中非零元的数量sum,这一数量实际上就是对应于data[]的下标sum!此时将这一数量存给rpos[i]即可。

    在插入新元素的时候,需要先将大于新元素行数及列数的元素往后挪动一格,在存放到空位。别忘了更新rpos[]以及相应变量。

    该题基本是第6周研讨作业,因而代码部分摘至给定的答案(),同时答案还给出了稀疏矩阵的乘法运算。

    #include <stdio.h>
    #include <stdlib.h>
    #define OK 1    //函数结果状态
    #define ERROR 0
    #define MAX 100
    typedef int Status;//函数结果状态类型
    
    typedef struct{
        int i,j;    //三元组的行号、列号;
        int e;      //三元组的值;
    }Triple;
    
    typedef struct{
        Triple data[MAX];//非零元三元组表示
        int rpos[MAX];  //稀疏矩阵三元组各行起始坐标
        int mu,nu,tu;   //矩阵的行数、列数和非零元个数
    }Matrix;
    
    void Input(Matrix *M,Matrix *N);
    Status CreateMatrix(Matrix *M);
    Status PrintMatrix(Matrix M);
    Status PlusMatrix(Matrix M, Matrix N, Matrix *D);
    Status MultMatrix(Matrix M, Matrix N, Matrix *Q);
    
    int main(){
        //freopen("in.txt","r",stdin);
        //freopen("output.txt","w",stdout);
        Matrix M,N,D,Q;
        Input(&M,&N);
        if(!PlusMatrix(M,N,&D))
            printf("They cannot be added.
    ");
        if(!MultMatrix(M,N,&Q))
            printf("They cannot be multiplied.
    ");
        return 0;
    }
    
    void Input(Matrix *M,Matrix *N){
        printf("Please input the rows and cols and number of the nonzero element:");
        if(!CreateMatrix(M))
            printf("Error Create M!
    ");
        PrintMatrix(*M);
    
        printf("Please input the rows and cols and number of the nonzero element:");
        if(!CreateMatrix(N))
            printf("Error Create N!
    ");
        PrintMatrix(*N);
    }
    
    Status CreateMatrix(Matrix *M){//创建稀疏矩阵,采取三元组存储
        int num[MAX]={0}; //对应行非零元个数
        int flag[MAX][MAX]={0};//标记对应位置是否已有非零元
        int i,j,e;  //非零元三元组的临时存储变量
        scanf(" %d%d%d",&M->mu,&M->nu,&M->tu);
        while(M->mu < 0 || M->nu < 0 || M->tu > M->mu * M->nu){//判断矩阵行数、列数和非零元个数是否合法
            printf("The rows,cols and number of nonzero element is out of normal range!!
    ");
            printf("Please input again:");
            scanf(" %d%d%d",&M->mu,&M->nu,&M->tu);
        }
    
        if(!M->tu) return OK;//全部为零元素,直接返回
    
        for(int k = 1;k <= M->tu;k++){//输入非零元
            printf("Please input the row,col,and data of element:");
            scanf(" %d%d%d",&i,&j,&e);
            //判断输入非零元行号、列号合法
            //判断是否非零元
            //判断该位置是否已有非零元
            int l,m;
            //寻找该三元组的位置
            if(k==1){
                M->data[k].i = i;
                M->data[k].j = j;
                M->data[k].e = e;
                continue;
            }
            for(l = 1;l < k && (i > M->data[l].i || (i == M->data[l].i && j > M->data[l].j));l++);
            for(m = k-1;m >= l;m--){//依次向后移动
                M->data[m+1] = M->data[m];
                //printf("%d
    ",M->data[m+1].i);
            }
            //保存数据
            M->data[l].i = i;
            M->data[l].j = j;
            M->data[l].e = e;
            //printf("%d	%d	%d",M->data[k].i,M->data[k].j,M->data[k].e);
            //printf("%d
    ",k);
        }
        //求各行非零元起始位置
        if(M->tu){//判断非零元个数是否为0
            for(int m = 1;m <= M->tu;m++)
                ++num[M->data[m].i];//求M中每行非零元素个数
            M->rpos[1] = 1;//起始位置赋值
            for(int m = 2;m <= M->tu;m++)
                M->rpos[m] = M->rpos[m-1] + num[m-1];
        }
        return OK;
    }
    
    Status PlusMatrix(Matrix M, Matrix N, Matrix *D){//求稀疏矩阵的和Q=M+N
        if(M.mu != N.mu || M.nu != N.nu)//检查稀疏矩阵M和N的行数和列数是否对应相等
            return ERROR;
        int i = 1,j = 1,k = 1;//各矩阵三元组移动临时变量
        D->mu = M.mu;
        D->nu = M.nu;
        D->tu = 0;
        if(M.tu*N.tu == 0)//零矩阵,直接返回
            return OK;
        while(i <= M.tu && j <= N.tu){//M和N均不为空
            if(M.data[i].i < N.data[j].i || (M.data[i].i == N.data[j].i && M.data[i].j < N.data[j].j)){//以行为主序,M中的节点在N前
                D->tu++;
                D->data[k++] = M.data[i++];//结构体赋值
            }
            else if(M.data[i].i == N.data[j].i && M.data[i].j == N.data[j].j){//M和N节点对应
                if(M.data[i].e+N.data[j].e){//M和N相加之和不为0
                    D->data[k].i=M.data[i].i;
                    D->data[k].j=M.data[i].j;
                    D->data[k++].e=M.data[i].e+N.data[j].e;
                    D->tu++;
                    //printf("%d
    ",D->data[k-1].e);
                }
                i++;
                j++;
            }
            else if(M.data[i].i > N.data[j].i ||(M.data[i].i == N.data[j].i && M.data[i].j > N.data[j].j)){//N节点在M前
                D->tu++;
                D->data[k++] = N.data[j++];
            }
        }
        while(i <= M.tu){//将矩阵N的剩余元素插入矩阵
            D->tu++;
            D->data[k++] = M.data[i++];
        }
        while(j <= N.tu){//将矩阵M的剩余元素插入矩阵
            D->tu++;
            D->data[k++] = N.data[j++];
        }
        //printf("%d
    ",k);
        printf("Matrix A plus Matrix B is D:
    ");
        PrintMatrix(*D);
        return OK;
    }
    
    Status MultMatrix(Matrix M, Matrix N, Matrix *Q){//进行矩阵M和N相乘
        int arow,brow,ccol,ctemp[MAX];
        int p,q,tp,i,t;//p,q,i为中间变量;tp,t分别为M的各行位置上限
        if(M.nu != N.mu)//判断M的列数和N的行数是否相等
            return ERROR;
        Q->mu = M.mu;
        Q->nu = N.nu;
        Q->tu = 0;
        if(M.tu*N.tu == 0)//判断矩阵是否为非零矩阵
            return OK;
        for(arow = 1;arow <= M.mu;arow++){//处理M的每一行
            for(i = 1;i <= N.nu;i++)//元素累加清零
                ctemp[i] = 0;
            Q->rpos[arow] = Q->tu+1;//起始坐标赋值
            if(arow < M.mu)//找到该行移动次数上限
                tp = M.rpos[arow+1];
            else
                tp = M.tu+1;
            for(p = M.rpos[arow];p < tp;p++){//求Q中第arow行的非零元
                brow = M.data[p].j;
                if(brow < N.mu)//找到N中该行移动次数上限
                    t = N.rpos[brow+1];
                else
                    t = N.tu+1;
                for(q = N.rpos[brow];q < t;q++){
                    ccol = N.data[q].j;//成绩元素在N中列号
                    ctemp[ccol] += M.data[p].e * N.data[q].e;
                }
            }
            for(ccol = 1;ccol <= Q->nu;ccol++){//存储非零元
                if(ctemp[ccol]){
                    Q->tu++;
                    Q->data[Q->tu].i = arow;
                    Q->data[Q->tu].j = ccol;
                    Q->data[Q->tu].e = ctemp[ccol];
                }
            }
        }
        printf("Matrix A multiply Matrix B is Q:
    ");
        PrintMatrix(*Q);
        return OK;
    }
    
    Status PrintMatrix(Matrix M){//打印矩阵
        int i,j,k = 1;//临时中间变量
        printf("The matrix is:
    ");
        for(i = 1;i <= M.mu;i++){//遍历矩阵
            for(j = 1;j <= M.nu;j++){
                if(i == M.data[k].i && j == M.data[k].j){//存在三元组匹配,输出
                    printf("%d	",M.data[k].e);
                    k++;
                }
                else
                    printf("0	");
            }
            printf("
    ");
        }
        printf("The matrix has %d rows, %d cols ,and %d nonzero elements.
    ",M.mu ,M.nu, M.tu);
        return OK;
    }
    
  • 相关阅读:
    Android调用Camera API 拍照导致图片变形
    [转]Android PorterDuff.Mode效果
    Android视频录制
    Android调用Camera API 拍照
    Android调用系统拍照
    android:windowIsTranslucent影响Activity生命周期onStop
    ProgressBar自定义之后图片拉伸的解决办法
    android开源ORM框架OrmLite使用教程
    AutoCompleteTextView源码分析
    Android App安全加固
  • 原文地址:https://www.cnblogs.com/J-StrawHat/p/13541380.html
Copyright © 2011-2022 走看看