热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

针对androidiosyuv旋转、镜像、格式转换、裁剪算法实现

https:blog.csdn.netdangxw_articledetails50903693移动端录像在yuv数据上存在如下问题:1.无论android还是ios

https://blog.csdn.net/dangxw_/article/details/50903693


移动端录像在yuv数据上存在如下问题:

 

1.无论android还是ios都不能直接从摄像头取出颜色空间为i420的数据,所以在编码前需要进行格式转换。

2.而且由于所取图像得分辨率必须是摄像头所提供分辨率中得一组,所以有可能需要裁剪。

3.另外由于1)想让无论用户哪个方向拿手机所录的视频内容永远“头朝上”,

  2)摄像头默认返回图像为横屏图像(宽大于长)所以需要旋转。

4.前置摄像头需要镜像。

 

YUV 颜色空间分类:https://zh.wikipedia.org/wiki/YUV

 

yuv 420 又分为:

I420: YYYYYYYY UU VV   =>YUV420P
YV12: YYYYYYYY VV UU   =>YUV420P
NV12: YYYYYYYY UVUV    =>YUV420SP
NV21: YYYYYYYY VUVU    =>YUV420SP

 

下面给出解决这四个问题所需要得算法:

 

1 格式转换:

nv21 转成i420

 

[cpp] view plain copy
  1. //nv21 to yuvi420  
  2. void NV21ToI420(uint8_t* dstyuv,uint8_t* data, int imageWidth, int imageHeight)  
  3. {  
  4.     int Ustart =imageWidth*imageHeight;  
  5.     int i,j;  
  6.     int uWidth = imageWidth/2;  
  7.     int uHeight = imageWidth/2;  
  8.     //y  
  9.     memcpy(dstyuv,data,imageWidth*imageHeight);  
  10.     int tempindex = 0 ;  
  11.     int srcindex= 0;  
  12.     //u  
  13.     for(i= 0 ;i 
  14.     {  
  15.    
  16.    
  17.         for(j = 0;j 
  18.         {  
  19.             dstyuv[Ustart&#43;tempindex&#43;j]&#61; data[Ustart&#43;(srcindex<<1)&#43;1];  
  20.             srcindex&#43;&#43;;  
  21.         }  
  22.         tempindex&#43;&#61; uWidth;  
  23.     }  
  24.    
  25.    
  26.     //v  
  27.     for (i &#61; 0; i < uHeight;i&#43;&#43;)  
  28.     {  
  29.    
  30.         for (j &#61; 0; j < uWidth;j&#43;&#43;)  
  31.         {  
  32.             dstyuv[Ustart&#43;tempindex &#43; j] &#61; data[Ustart &#43; (srcindex << 1 )];  
  33.             srcindex&#43;&#43;;  
  34.         }  
  35.         tempindex&#43;&#61; uWidth;  
  36.     }  
  37. }  





 

其实就是改变了uv的位置。

 

2 裁剪&#xff1a;

[cpp] view plain copy
  1. //crop yuv data  
  2. int crop_yuv (char* data, char*dst, intwidth, intheight,  
  3.         int goalwidth, int goalheight) {  
  4.    
  5.     int i, j;  
  6.     int h_div &#61; 0, w_div &#61; 0;  
  7.     w_div&#61; (width - goalwidth) / 2;  
  8.     if (w_div % 2)  
  9.         w_div--;  
  10.     h_div&#61; (height - goalheight) / 2;  
  11.     if (h_div % 2)  
  12.         h_div--;  
  13.     //u_div &#61; (height-goalheight)/4;  
  14.     int src_y_length &#61; width *height;  
  15.     int dst_y_length &#61;goalwidth * goalheight;  
  16.     for (i &#61; 0; i 
  17.         for (j &#61; 0; j 
  18.             dst[i* goalwidth &#43; j] &#61; data[(i &#43; h_div) * width &#43; j &#43; w_div];  
  19.         }  
  20.     int index &#61; dst_y_length;  
  21.     int src_begin &#61;src_y_length &#43; h_div * width / 4;  
  22.     int src_u_length &#61;src_y_length / 4;  
  23.     int dst_u_length &#61;dst_y_length / 4;  
  24.     for (i &#61; 0; i 
  25.         for (j &#61; 0; j 
  26.             int p &#61; src_begin &#43; i *(width >> 1) &#43; (w_div >> 1) &#43; j;  
  27.             dst[index]&#61; data[p];  
  28.             dst[dst_u_length&#43; index&#43;&#43;] &#61; data[p &#43; src_u_length];  
  29.         }  
  30.    
  31.     return 0;  
  32. }  





 

 

3 旋转&#xff1a;

分为四个方向

 

 

 

旋转&#xff1a;

以顺时针旋转270度为例作图&#xff1a;

 

Y1

Y2

Y3

Y4

Y5

Y6

Y7

Y8

Y9

Y10

Y11

Y12

Y13

Y14

Y15

Y16

U1

U2

U3

U4

V1

V2

V3

V4

原图

 

 

 

Y4

Y8

Y12

Y16

Y3

Y7

Y11

Y15

Y2

Y6

Y10

Y14

Y1

Y5

Y9

Y13

U2

U4

U1

U3

V2

V4

V1

V3

旋转后

 

u值的第i 行j列 对应原 数据的下标为&#xff1a;  ustart&#43;uw*j-i;

去除index的乘除法运算后&#xff1a;

//i420 顺时针 270

[cpp] view plain copy
  1. int rotateYUV420Degree270(uint8_t* dstyuv,uint8_t* srcdata, int imageWidth, int imageHeight) {  
  2.    
  3.     int i &#61; 0, j &#61; 0;  
  4.    
  5.     int index &#61; 0;  
  6.     int tempindex &#61; 0;  
  7.     int div &#61; 0;  
  8.     for (i &#61; 0; i 
  9.         div&#61; i &#43;1;  
  10.         tempindex&#61; 0;  
  11.         for (j &#61; 0; j 
  12.    
  13.             tempindex&#43;&#61; imageWidth;  
  14.             dstyuv[index&#43;&#43;]&#61; srcdata[tempindex-div];  
  15.         }  
  16.     }  
  17.    
  18.     int start &#61;imageWidth*imageHeight;  
  19.     int udiv &#61; imageWidth *imageHeight / 4;  
  20.    
  21.     int uWidth &#61; imageWidth /2;  
  22.     int uHeight &#61; imageHeight /2;  
  23.     index&#61; start;  
  24.     for (i &#61; 0; i < uHeight;i&#43;&#43;) {  
  25.         div&#61; i &#43;1;  
  26.         tempindex&#61; start;  
  27.         for (j &#61; 0; j < uWidth;j&#43;&#43;) {  
  28.             tempindex &#43;&#61; uWidth;  
  29.             dstyuv[index]&#61; srcdata[tempindex-div];  
  30.             dstyuv[index&#43;udiv]&#61; srcdata[tempindex-div&#43;udiv];  
  31.             index&#43;&#43;;  
  32.         }  
  33.     }  
  34.    
  35.     return 0;  
  36.    
  37. }  





//i420 顺时针旋转 180&#xff1b;

[cpp] view plain copy
  1. int rotateYUV420Degree180(uint8_t* dstyuv,uint8_t* srcdata, int imageWidth, int imageHeight)  
  2. {  
  3.    
  4.     int i &#61; 0, j &#61; 0;  
  5.    
  6.     int index &#61; 0;  
  7.     int tempindex &#61; 0;  
  8.    
  9.     int ustart &#61; imageWidth *imageHeight;  
  10.     tempindex&#61; ustart;  
  11.     for (i &#61; 0; i 
  12.    
  13.         tempindex-&#61; imageWidth;  
  14.         for (j &#61; 0; j 
  15.    
  16.             dstyuv[index&#43;&#43;] &#61; srcdata[tempindex &#43; j];  
  17.         }  
  18.     }  
  19.    
  20.     int udiv &#61; imageWidth *imageHeight / 4;  
  21.    
  22.     int uWidth &#61; imageWidth /2;  
  23.     int uHeight &#61; imageHeight /2;  
  24.     index&#61; ustart;  
  25.     tempindex&#61; ustart&#43;udiv;  
  26.     for (i &#61; 0; i < uHeight;i&#43;&#43;) {  
  27.    
  28.         tempindex-&#61; uWidth;  
  29.         for (j &#61; 0; j < uWidth;j&#43;&#43;) {  
  30.    
  31.             dstyuv[index]&#61; srcdata[tempindex &#43; j];  
  32.             dstyuv[index&#43; udiv] &#61; srcdata[tempindex &#43; j &#43; udiv];  
  33.             index&#43;&#43;;  
  34.         }  
  35.     }  
  36.     return 0;  
  37. }  





 

 

顺时针 90度&#xff1a;

 

[cpp] view plain copy
  1. //i420顺时针旋转90 &#xff1b;  
  2. int rotateYUV420Degree90(uint8_t* dstyuv,uint8_t* srcdata, int imageWidth, int imageHeight) {  
  3.    
  4.     int i &#61; 0, j &#61; 0;  
  5.    
  6.     int index &#61; 0;  
  7.     int tempindex &#61; 0;  
  8.     int div &#61; 0;  
  9.     int ustart &#61; imageWidth *imageHeight;  
  10.     for (i &#61; 0; i 
  11.         div&#61; i;  
  12.         tempindex&#61; ustart;  
  13.         for (j &#61; 0; j 
  14.    
  15.             tempindex-&#61; imageWidth;  
  16.    
  17.             dstyuv[index&#43;&#43;]&#61; srcdata[tempindex &#43; div];  
  18.         }  
  19.     }  
  20.    
  21.    
  22.     int udiv &#61; imageWidth *imageHeight / 4;  
  23.    
  24.     int uWidth &#61; imageWidth /2;  
  25.     int uHeight &#61; imageHeight /2;  
  26.     index&#61; ustart;  
  27.     for (i &#61; 0; i < uHeight;i&#43;&#43;) {  
  28.         div&#61; i ;  
  29.         tempindex&#61; ustart&#43;udiv;  
  30.         for (j &#61; 0; j < uWidth;j&#43;&#43;) {  
  31.             tempindex-&#61; uWidth;  
  32.             dstyuv[index]&#61; srcdata[tempindex &#43; div];  
  33.             dstyuv[index&#43; udiv] &#61; srcdata[tempindex &#43; div &#43; udiv];  
  34.             index&#43;&#43;;  
  35.         }  
  36.     }  
  37.     return 0;  
  38.    
  39. }  



 

如果从摄像头取出数据&#xff0c;这样一步步的历遍&#xff0c;在低配手机上是满足不了需求的。其实这三个步骤中有很多中间步骤是可以省去的&#xff0c;比如&#xff1a;将a放到b 位置&#xff0c;再将b位置上的数据取出放到c位置&#xff0c;那么可以直接将a放到c位置。

所以需要优化以上三类问题所用的算法将其整合。结果如下&#xff1a;

 

[cpp] view plain copy
  1. void detailPic0(uint8_t* d, uint8_t* yuv_temp, int nw, int nh, int w, int h) {  
  2.     int deleteW &#61; (nw - w) / 2;  
  3.     int deleteH &#61; (nh - h) / 2;  
  4.     //处理y 旋转加裁剪  
  5.     int i, j;  
  6.     int index &#61; 0;  
  7.     for (j &#61; deleteH; j < nh- deleteH; j&#43;&#43;) {  
  8.         for (i &#61; deleteW; i < nw- deleteW; i&#43;&#43;)  
  9.             yuv_temp[index&#43;&#43;]&#61; d[j * nw &#43; i];  
  10.     }  
  11.    
  12.     //处理u  
  13.     index&#61; w * h;  
  14.    
  15.     for (i &#61; nh &#43; deleteH / 2;i < nh / 2 * 3 - deleteH / 2; i&#43;&#43;)  
  16.         for (j &#61; deleteW &#43; 1; j< nw - deleteW; j &#43;&#61; 2)  
  17.             yuv_temp[index&#43;&#43;]&#61; d[i * nw &#43; j];  
  18.    
  19.     //处理v 旋转裁剪加格式转换  
  20.     for (i &#61; nh &#43; deleteH / 2;i < nh / 2 * 3 - deleteH / 2; i&#43;&#43;)  
  21.         for (j &#61; deleteW; j < nw- deleteW; j &#43;&#61; 2)  
  22.             yuv_temp[index&#43;&#43;]&#61; d[i * nw &#43; j];  
  23.    
  24. }  



[cpp] view plain copy
  1. //针对横屏前摄像头 nv21 to 420sp  裁剪&#xff0c;旋转  
  2. void detailPic180(uint8_t* d, uint8_t* yuv_temp, int nw, int nh, int w, int h) {  
  3.     int deleteW &#61; (nw - w) / 2;  
  4.     int deleteH &#61; (nh - h) / 2;  
  5.     //处理y 旋转加裁剪  
  6.     int i, j;  
  7.     int index &#61; w * h;  
  8.     for (j &#61; deleteH; j < nh- deleteH; j&#43;&#43;) {  
  9.         for (i &#61; deleteW; i < nw- deleteW; i&#43;&#43;)  
  10.             yuv_temp[--index]&#61; d[j * nw &#43; i];  
  11.     }  
  12.    
  13.     //处理u  
  14.     index&#61; w * h * 5 / 4;  
  15.    
  16.     for (i &#61; nh &#43; deleteH / 2;i < nh / 2 * 3 - deleteH / 2; i&#43;&#43;)  
  17.         for (j &#61; deleteW &#43; 1; j< nw - deleteW; j &#43;&#61; 2)  
  18.             yuv_temp[--index]&#61; d[i * nw &#43; j];  
  19.    
  20.     //处理v 旋转裁剪加格式转换  
  21.     index&#61; w * h * 3 / 2;  
  22.     for (i &#61; nh &#43; deleteH / 2;i < nh / 2 * 3 - deleteH / 2; i&#43;&#43;)  
  23.         for (j &#61; deleteW; j < nw- deleteW; j &#43;&#61; 2)  
  24.             yuv_temp[--index]&#61; d[i * nw &#43; j];  
  25.    
  26. }  






[cpp] view plain copy
  1. void detailPic90(uint8_t* d, uint8_t* yuv_temp, int nw, int nh, int w, int h) {  
  2.    
  3.    
  4.    
  5.    
  6.    
  7.     int deleteW &#61; (nw - h) / 2;  
  8.     int deleteH &#61; (nh - w) / 2;  
  9.    
  10.     int i, j;  
  11.      }*/  
  12.     for (i &#61; 0; i < h; i&#43;&#43;){  
  13.         for (j &#61; 0; j < w; j&#43;&#43;){  
  14.             yuv_temp[(h- i) * w - 1 - j] &#61; d[nw * (deleteH &#43; j) &#43; nw - deleteW  
  15.                     -i];  
  16.         }  
  17.     }  
  18.    
  19.     int index &#61; w * h;  
  20.     for (i &#61; deleteW &#43; 1; i< nw - deleteW; i &#43;&#61; 2)  
  21.         for (j &#61; nh / 2 * 3 -deleteH / 2; j > nh &#43; deleteH / 2; j--)  
  22.             yuv_temp[index&#43;&#43;]&#61; d[(j - 1) * nw &#43; i];  
  23.    
  24.     for (i &#61; deleteW; i < nw- deleteW; i &#43;&#61; 2)  
  25.         for (j &#61; nh / 2 * 3 -deleteH / 2; j > nh &#43; deleteH / 2; j--)  
  26.             yuv_temp[index&#43;&#43;]&#61; d[(j - 1) * nw &#43; i];  
  27.    
  28. }  
  29.    





[cpp] view plain copy
  1. void detailPic270(uint8_t* d, uint8_t* yuv_temp, int nw, int nh, int w, int h) {  
  2.     int deleteW &#61; (nw - h) / 2;  
  3.     int deleteH &#61; (nh - w) / 2;  
  4.     int i, j;  
  5.     //处理y 旋转加裁剪  
  6.     for (i &#61; 0; i < h; i&#43;&#43;){  
  7.         for (j &#61; 0; j < w; j&#43;&#43;){  
  8.             yuv_temp[i* w &#43; j] &#61; d[nw * (deleteH &#43; j) &#43; nw - deleteW - i];  
  9.         }  
  10.     }  
  11.    
  12.     //处理u 旋转裁剪加格式转换  
  13.     int index &#61; w * h;  
  14.     for (i &#61; nw - deleteW - 1;i > deleteW; i -&#61; 2)  
  15.         for (j &#61; nh &#43; deleteH / 2;j < nh / 2 * 3 - deleteH / 2; j&#43;&#43;)  
  16.             yuv_temp[index&#43;&#43;]&#61; d[(j) * nw &#43; i];  
  17.    
  18.     //处理v 旋转裁剪加格式转换  
  19.    
  20.     for (i &#61; nw - deleteW - 2;i >&#61; deleteW; i -&#61; 2)  
  21.         for (j &#61; nh &#43; deleteH / 2;j < nh / 2 * 3 - deleteH / 2; j&#43;&#43;)  
  22.             yuv_temp[index&#43;&#43;]&#61; d[(j) * nw &#43; i];  
  23.    
  24. }  
  25.    





 

注&#xff1a;没有优化&#xff0c;消除index的乘法后效果肯定会更好。

 

4 镜像&#xff1a;

 

[cpp] view plain copy
  1. //mirro 原址的  
  2. void Mirror(uint8_t* yuv_temp, int nw, int nh, int w,  
  3.         int h) {  
  4.     int deleteW &#61; (nw - h) / 2;  
  5.     int deleteH &#61; (nh - w) / 2;  
  6.     int i, j;  
  7.      
  8.     int a, b;  
  9.     uint8_ttemp;  
  10.     //mirror y  
  11.     for (i &#61; 0; i < h; i&#43;&#43;){  
  12.         a&#61; i * w;  
  13.         b&#61; (i &#43; 1) * w - 1;  
  14.         while (a < b) {  
  15.             temp&#61; yuv_temp[a];  
  16.             yuv_temp[a]&#61; yuv_temp[b];  
  17.             yuv_temp[b]&#61; temp;  
  18.             a&#43;&#43;;  
  19.             b--;  
  20.         }  
  21.     }  
  22.     //mirror u  
  23.     int uindex &#61; w * h;  
  24.     for (i &#61; 0; i < h / 2;i&#43;&#43;) {  
  25.         a &#61; i * w / 2;  
  26.         b&#61; (i &#43; 1) * w / 2 - 1;  
  27.         while (a < b) {  
  28.             temp&#61; yuv_temp[a &#43; uindex];  
  29.             yuv_temp[a&#43; uindex] &#61; yuv_temp[b &#43; uindex];  
  30.             yuv_temp[b&#43; uindex] &#61; temp;  
  31.             a&#43;&#43;;  
  32.             b--;  
  33.         }  
  34.     }  
  35.     //mirror v  
  36.     uindex&#61; w * h / 4 * 5;  
  37.     for (i &#61; 0; i < h / 2;i&#43;&#43;) {  
  38.         a&#61; i * w / 2;  
  39.         b&#61; (i &#43; 1) * w / 2 - 1;  
  40.         while (a < b) {  
  41.             temp&#61; yuv_temp[a &#43; uindex];  
  42.             yuv_temp[a&#43; uindex] &#61; yuv_temp[b &#43; uindex];  
  43.             yuv_temp[b&#43; uindex] &#61; temp;  
  44.             a&#43;&#43;;  
  45.             b--;  
  46.         }  
  47.     }  
  48.    
  49. }  





 

 

由于当初忽略了镜像&#xff0c;所以并没有把镜像也和其他三个算法和并到一起。不过测试还是通过的。

 

如果集成ffmpeg或者opencv&#xff0c;可以使用ffmpeg的sws&#xff0c;filter 或者opencv的cvtcolor都可以轻松实现部分功能&#xff0c;不过跟踪过ffmpeg sws的源码&#xff0c;发现效率较低&#xff0c;代码实现较差。如果追求处理效率&#xff0c;并且以上优化的算法仍不能满足&#xff0c;建议使用libyuv&#xff0c;其中试用了很多汇编指令加速&#xff0c;效率惊人。



推荐阅读
  • 本文介绍了九度OnlineJudge中的1002题目“Grading”的解决方法。该题目要求设计一个公平的评分过程,将每个考题分配给3个独立的专家,如果他们的评分不一致,则需要请一位裁判做出最终决定。文章详细描述了评分规则,并给出了解决该问题的程序。 ... [详细]
  • 在Android开发中,使用Picasso库可以实现对网络图片的等比例缩放。本文介绍了使用Picasso库进行图片缩放的方法,并提供了具体的代码实现。通过获取图片的宽高,计算目标宽度和高度,并创建新图实现等比例缩放。 ... [详细]
  • 本文介绍了P1651题目的描述和要求,以及计算能搭建的塔的最大高度的方法。通过动态规划和状压技术,将问题转化为求解差值的问题,并定义了相应的状态。最终得出了计算最大高度的解法。 ... [详细]
  • SpringBoot整合SpringSecurity+JWT实现单点登录
    SpringBoot整合SpringSecurity+JWT实现单点登录,Go语言社区,Golang程序员人脉社 ... [详细]
  • Android自定义控件绘图篇之Paint函数大汇总
    本文介绍了Android自定义控件绘图篇中的Paint函数大汇总,包括重置画笔、设置颜色、设置透明度、设置样式、设置宽度、设置抗锯齿等功能。通过学习这些函数,可以更好地掌握Paint的用法。 ... [详细]
  • 花瓣|目标值_Compose 动画边学边做夏日彩虹
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了Compose动画边学边做-夏日彩虹相关的知识,希望对你有一定的参考价值。引言Comp ... [详细]
  • python3 logging
    python3logginghttps:docs.python.org3.5librarylogging.html,先3.5是因为我当前的python版本是3.5之所 ... [详细]
  • 使用nodejs爬取b站番剧数据,计算最佳追番推荐
    本文介绍了如何使用nodejs爬取b站番剧数据,并通过计算得出最佳追番推荐。通过调用相关接口获取番剧数据和评分数据,以及使用相应的算法进行计算。该方法可以帮助用户找到适合自己的番剧进行观看。 ... [详细]
  • 生成式对抗网络模型综述摘要生成式对抗网络模型(GAN)是基于深度学习的一种强大的生成模型,可以应用于计算机视觉、自然语言处理、半监督学习等重要领域。生成式对抗网络 ... [详细]
  • 云原生边缘计算之KubeEdge简介及功能特点
    本文介绍了云原生边缘计算中的KubeEdge系统,该系统是一个开源系统,用于将容器化应用程序编排功能扩展到Edge的主机。它基于Kubernetes构建,并为网络应用程序提供基础架构支持。同时,KubeEdge具有离线模式、基于Kubernetes的节点、群集、应用程序和设备管理、资源优化等特点。此外,KubeEdge还支持跨平台工作,在私有、公共和混合云中都可以运行。同时,KubeEdge还提供数据管理和数据分析管道引擎的支持。最后,本文还介绍了KubeEdge系统生成证书的方法。 ... [详细]
  • 向QTextEdit拖放文件的方法及实现步骤
    本文介绍了在使用QTextEdit时如何实现拖放文件的功能,包括相关的方法和实现步骤。通过重写dragEnterEvent和dropEvent函数,并结合QMimeData和QUrl等类,可以轻松实现向QTextEdit拖放文件的功能。详细的代码实现和说明可以参考本文提供的示例代码。 ... [详细]
  • CSS3选择器的使用方法详解,提高Web开发效率和精准度
    本文详细介绍了CSS3新增的选择器方法,包括属性选择器的使用。通过CSS3选择器,可以提高Web开发的效率和精准度,使得查找元素更加方便和快捷。同时,本文还对属性选择器的各种用法进行了详细解释,并给出了相应的代码示例。通过学习本文,读者可以更好地掌握CSS3选择器的使用方法,提升自己的Web开发能力。 ... [详细]
  • 解决Cydia数据库错误:could not open file /var/lib/dpkg/status 的方法
    本文介绍了解决iOS系统中Cydia数据库错误的方法。通过使用苹果电脑上的Impactor工具和NewTerm软件,以及ifunbox工具和终端命令,可以解决该问题。具体步骤包括下载所需工具、连接手机到电脑、安装NewTerm、下载ifunbox并注册Dropbox账号、下载并解压lib.zip文件、将lib文件夹拖入Books文件夹中,并将lib文件夹拷贝到/var/目录下。以上方法适用于已经越狱且出现Cydia数据库错误的iPhone手机。 ... [详细]
  • 本文介绍了解决二叉树层序创建问题的方法。通过使用队列结构体和二叉树结构体,实现了入队和出队操作,并提供了判断队列是否为空的函数。详细介绍了解决该问题的步骤和流程。 ... [详细]
  • 《数据结构》学习笔记3——串匹配算法性能评估
    本文主要讨论串匹配算法的性能评估,包括模式匹配、字符种类数量、算法复杂度等内容。通过借助C++中的头文件和库,可以实现对串的匹配操作。其中蛮力算法的复杂度为O(m*n),通过随机取出长度为m的子串作为模式P,在文本T中进行匹配,统计平均复杂度。对于成功和失败的匹配分别进行测试,分析其平均复杂度。详情请参考相关学习资源。 ... [详细]
author-avatar
万宝盛华猎头
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有